如何在线程或定时器中访问 HttpServerUtility.MapPath 方法?
Posted
技术标签:
【中文标题】如何在线程或定时器中访问 HttpServerUtility.MapPath 方法?【英文标题】:How to access the HttpServerUtility.MapPath method in a Thread or Timer? 【发布时间】:2010-09-11 20:00:36 【问题描述】:我在我的 Asp.Net 应用程序中使用了System.Timers.Timer
,我需要使用似乎只能通过HttpContext.Current.Server.MapPath
获得的HttpServerUtility.MapPath
方法。
问题是当Timer.Elapsed
事件触发时HttpContext.Current
是null
。
还有其他方法可以获取对 HttpServerUtility 对象的引用吗? 我可以将它注入我的类的构造函数中。安全吗?我如何确定它不会在当前请求结束时被垃圾收集?
谢谢!
【问题讨论】:
【参考方案1】:我认为当时它为 null 的原因(如果您考虑一下的话),是因为计时器已过事件不会作为 HTTP 请求的一部分发生(因此没有上下文)。它是由您的服务器上的某些东西引起的。
【讨论】:
【参考方案2】:能不能在启动定时器之前不调用 MapPath 函数,只缓存结果?在 tick 事件中调用 MapPath 是否绝对有必要?
【讨论】:
【参考方案3】:当计时器结束时,没有当前的 HTTP 上下文。这是因为定时器事件与特定的 HTTP 请求无关。
您应该做的是在 HTTP 上下文可用的地方使用 HttpServerUtility.MapPath。您可以在请求管道事件之一(例如 Page_Load)或 Global.asax 事件(例如 Application_Start)中执行此操作。
将 MapPath 结果分配给可从 Timer.Elapsed 事件访问的变量,您可以在其中使用 Path.Combine 获取所需特定文件的位置。
【讨论】:
【参考方案4】:可以使用HostingEnvironment.MapPath()
代替HttpContext.Current.Server.MapPath()
不过,我还没有在线程或计时器事件中尝试过。
我考虑过的一些(不可行的)解决方案;
我在HttpServerUtility
上关心的唯一方法是MapPath
。因此,作为替代方案,我可以使用AppDomain.CurrentDomain.BaseDirectory
并以此构建我的路径。 但如果您的应用使用虚拟目录,这将失败(我的使用)。
另一种方法:
将我需要的所有路径添加到 Global
类。在Application_Start
中解析这些路径。
【讨论】:
但请注意,上述内容在更高版本的 IIS 中不起作用。在 IIS7 中,可以在 http 请求之外调用应用程序启动。也就是代码示例。我确信 HostingEnvironment.MapPath() 仍然会像以前一样工作。 但是 HostingEnvironment.MapPath() 如果您传递它和空字符串以直接获取文件夹路径,则会出错... HttpContext.Current.Server.MapPath(""); -> 工作 HostingEnvironment.MapPath(""); -> 引发错误【参考方案5】:我不知道这是否会解决您的虚拟目录问题,但我将它用于 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('/', '\\');
【讨论】:
path.Replace("~", string.Empty) 应该是 path.Replace('~', '.')【参考方案6】:HostingEnvironment 不是完美的解决方案,因为它是一个非常难以模拟的类(请参阅 How to unit test code that uses HostingEnvironment.MapPath)。
对于那些需要可测试性的人,更好的方法可能是创建自己的路径映射器接口,如https://***.com/a/1231962/85196 所建议的那样,除了将其实现为
public class ServerPathMapper : IPathMapper
public string MapPath(string relativePath)
return HostingEnvironment.MapPath(relativePath);
结果很容易模拟,在内部使用 HostingEnvironment,甚至可以同时寻址 ase69s's concern。
【讨论】:
这使我能够为 Web API 项目提供路径解析的实现,而无需依赖它所引用的库中的 System.Web 或 System.Net。 +1 为这种方法的 DI 和可测试性点赞以上是关于如何在线程或定时器中访问 HttpServerUtility.MapPath 方法?的主要内容,如果未能解决你的问题,请参考以下文章
C#如何在BackgroundWorker 后台线程中使用定时器?