为什么当前的ASP.NET MVC应用程序根虚拟路径在另一个线程/任务中不可用?
问题描述:
我最近的一个项目是根据一些提醒配置发送提醒电子邮件。电子邮件发送是通过使用Quartz.net.的异步作业实现的,它需要在应用程序中为实体包含永久链接。为什么当前的ASP.NET MVC应用程序根虚拟路径在另一个线程/任务中不可用?
但是,为了获得这个永久链接,我必须能够根据存储在作业队列中的标识符来计算完整的URL。答案并不简单,因为HttpContext
在线程的上下文中不可用。
一种解决方案是将应用程序根路径存储在队列中并从那里使用它。另一种方法是使用一个函数如下所示:
public static String GetCurrentBasePath(String prefix = "http://")
{
return String.Format("{0}{1}{2}",
prefix, // protocol
System.Net.Dns.GetHostEntry("").HostName, // host
System.Web.HttpRuntime.AppDomainAppVirtualPath // virtual application path
);
}
然而,这具有(重度)的限制,因为必须提供协议,并且还返回hostname
,而不是domain name
,从而使之无用具有多个时Web应用程序绑定到同一主机。
问题:在另一个线程/任务中是否可以使用Web应用程序的基本路径?。我认为其他线程/任务上下文以某种方式连接到ApplicationPool
而不是WebApp
,并且因为多个WebApp
可以使用相同的ApplicationPool
,所以在线程上下文和WebApp
之间没有直接连接。
答
我不知道你是如何调用这个。但从我的经验来看,并行(如你所提到的)失去了HttpContext。也就是说,没有什么可以阻止你使用带有你需要的字符串值的配置变量。当然,取决于这个值如何动态化,这可能不是最佳的行动方案。但请记住,上面所做的计算很昂贵,所以请记住在本地存储值。
我相信这里的最佳解决方案(假设你知道上下文值,我不明白你为什么不能/不会)将设置一些变量并完全避免计算。
static readonly string hostName = "your-host";
static readonly string virtualPath = "your-virtual-path";
public static String GetCurrentBasePath(String prefix = "http://")
{
return String.Format("{0}{1}{2}",
prefix, // protocol
hostName, // host
virtualPath // virtual application path
);
}
我使用Quarz.net,但它使用一个新的线程,任务(TPL)或异步/ AWAIT是重复的。基本上,它在IIS中运行作业,而不是创建Windows服务或类似的东西。 – Alexei
没错。正如我所说,对我来说,我认为如果你知道你想要计算的值是什么,我认为你最好将它们设置为内部只读值。为您提供线程安全并节省您的周期。 – pimbrouwers