如何在线程或定时器中访问 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.Currentnull

还有其他方法可以获取对 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语言 用定时器 模拟多线程

C#如何在BackgroundWorker 后台线程中使用定时器?

如何在活动中显示计时器?

在linux环境中,如何实现多线程中使用多个定时器,POSIX定时器可以吗,如何用?

MFC中如何建立和结束一个线程

推送通知或带计时器的线程