如何访问Thread或Timer中的HttpServerUtility.MapPath方法?

我在我的Asp.Net应用程序中使用System.Timers.Timer ,我需要使用HttpServerUtility.MapPath方法,似乎只能通过HttpContext.Current.Server.MapPath 。 问题是当Timer.Elapsed事件触发时HttpContext.Currentnull

有没有另一种方式来获取对HttpServerUtility对象的引用? 我可以在我的类的构造函数中注入它。 安全吗? 我如何确定在当前请求结束时不会收集垃圾?

谢谢!

可以使用HostingEnvironment.MapPath()而不是HttpContext.Current.Server.MapPath()

我还没有在线程或计时器事件中尝试过。


我考虑的一些(不可行的)解决scheme;

  • 我唯一关心HttpServerUtilityMapPath 。 所以作为替代scheme,我可以使用AppDomain.CurrentDomain.BaseDirectory并从此构build我的path。 但是,如果你的应用程序使用虚拟目录 (我的), 这将失败

  • 另一种方法:将所有我需要的path添加到Global类。 在Application_Startparsing这些path。

我不知道这是否会解决你的虚拟目录问题,但我用这个MapPath:

 public static string MapPath(string path) { if (HttpContext.Current != null) return HttpContext.Current.Server.MapPath(path); return HttpRuntime.AppDomainAppPath + path.Replace("~", string.Empty).Replace('/', '\\'); } 

HostingEnvironment不是完美的解决scheme,因为它是一个非常困难的类来模拟(请参阅如何unit testing使用HostingEnvironment.MapPath的代码 )。

对于需要可testing性的用户来说,更好的方法可能是按照https://stackoverflow.com/a/1231962/85196build议的方式创build自己的path映射器接口,除了将其实现为;

 public class ServerPathMapper : IPathMapper { public string MapPath(string relativePath) { return HostingEnvironment.MapPath(relativePath); } } 

结果很容易嘲弄,内部使用HostingEnvironment,甚至可能同时解决ase69s的问题 。

你可以在启动定时器之前不调用MapPath函数,并简单地caching结果? 在tick事件中有MapPath调用是绝对必要的吗?

当计时器过去时,没有当前的HTTP上下文。 这是因为计时器事件与特定的HTTP请求无关。

你应该做的是使用HTTP上下文可用的HttpServerUtility.MapPath。 您可以在请求pipe道事件之一(如Page_Load)或Global.asax事件(如Application_Start)中执行此操作。

将MapPath结果分配给可从Timer.Elapsed事件访问的variables,您可以在其中使用Path.Combine来获取所需的特定文件的位置。

我认为当时为什么它为空的原因(如果你想一想)是因为计时器已经过的事件不作为HTTP请求的一部分发生(因此没有上下文)。 这是由你的服务器上的东西造成的。