12

我写了一个产生后台线程的 HttpModule。我正在使用线程,就像在进程中运行的计划任务一样,这真的很方便。

跟踪此线程的最佳做法是什么?我以前从来没有这样做过,我对它的某些方面有点困惑:

  1. 我怎么知道线程是否仍在运行?我看到它完成了它的工作,但是还有其他方法可以知道它是否还活着?我下载了 ProcMon,但 w3wp.exe 产生了大量线程,所以我不知道哪个是我的线程。我给它起了名字,但这并没有帮助。

  2. 如果线程死了,我如何“抓住”线程?是否有某种 Dispose 方法可以让它写入 EventLog 或者如果它失败了?“垂死宣言”之类的?

  3. 如何主动停止线程?如果我想让它停止运行这个后台进程,如何在不反弹 IIS 的情况下杀死它?

  4. 无论如何要重新启动它,独立于 HttpModule 吗?(我猜这个答案是否定的……)

编辑:只是为了澄清,目的是我的线程永远不会消失。它运行一个函数,然后进入睡眠状态几分钟,然后唤醒并再次运行该函数。这不像是完成一项任务然后结束。

4

2 回答 2

10

当 Jeff 制作 Stackoverflow 时,他遇到了类似的问题。

他的解决方案是使用缓存过期。您将某些内容放入缓存中,然后当它过期时,会在非面向用户的线程中触发一个事件。在过期的事件处理程序中,您插入一些代码以将项目重新添加到缓存中,并为您的应用程序执行任何需要完成的内务工作

使用这种技术,您的子问题很容易得到回答:

  1. 您检查该项目是否仍在缓存中。
  2. 如果该项目不在缓存中,请重新添加它。
  3. 从缓存中删除缓存项。
  4. 将项目添加回缓存。

您可以制作一个小的管理页面来配置这些选项。

这为您提供了一种在 Web 应用程序中大致计时内务处理过程的好方法。它不需要单独的 Windows 服务,这是一个巨大的胜利。

于 2009-03-17T17:27:06.553 回答
6

根据我的经验,你可以让它“足够好”,但并不完美。我建议在 Windows 服务中实现您的重复任务。根据任务所做的事情,Windows 服务可能甚至不必与 Web 应用程序对话,反之亦然,例如,如果两者都使用同一个数据库。否则,您仍然可以使用例如 WCF 进行通信。

最大的好处是:windows服务将随操作系统启动,您可以使用控制面板轻松配置、启动和停止它,您通过Windows事件日志内置监控,您可以独立更新后台服务和Web应用程序等等

如果这不是一个选项,例如因为您处于共享托管环境中,我会推荐以下内容:

  1. 在 Application_start (Global.asax) 中启动后台线程,并将线程引用存储在静态变量中。
  2. 使用 try/catch 包装在后台线程上调用的每个方法,因为从 .NET 2.0 开始,后台线程上的每个未处理异常都会关闭应用程序。(它将在下一个请求时重新启动,但它会减慢下一个请求,杀死所有当前会话和缓存,当然在下一个请求之前不会有任何计时器处于活动状态。)
  3. 在每个请求上(实现了一个 HttpModule 或再次在 Global.asax 中),检查全局变量中的 Thread 实例(它是否仍然!= null,线程是否处于活动状态并正在运行等)。如果没有,请调用重新启动代码。在重新启动部分使用锁定以确保线程不会同时创建两次。

即使那样,如果您没有全天候的常规流量,您也无法确定您的后台线程是否始终在运行。另请记住,在共享托管环境中,如果几个小时内没有活动,关闭应用程序池是很常见的。您可以尝试通过在您自己的网络上的客户端计算机上设置计划任务来改进这一点,每隔几分钟对您的应用程序执行一次轻量级 HTTP 请求,以确保您的应用程序始终运行。

于 2009-03-17T17:16:27.110 回答