I have written an HttpModule that spawns a background thread. I'm using the thread like a Scheduled Task that runs in-process, which is really handy.
我写了一个HttpModule,它产生了一个后台线程。我正在使用线程,就像在进程中运行的Scheduled Task一样,这非常方便。
What are best practices for keeping track of this thread? I've never done this before, and I'm a little confused about some aspects of it:
跟踪此主题的最佳做法是什么?我以前从未这样做过,而且我对它的某些方面感到有些困惑:
-
How do I know if the thread is still running? I see it do its job, but is there another way to know if it's still alive? I downloaded ProcMon, but w3wp.exe spawns a boatload of threads, so I had no idea which was my thread. I named it, but that didn't help.
我怎么知道线程是否仍在运行?我认为它可以完成它的工作,但还有另一种方法可以知道它是否还活着吗?我下载了ProcMon,但w3wp.exe产生了大量的线程,所以我不知道我的线程是什么。我把它命名为,但这没有用。
-
How do I "catch" the thread if it dies? Is there some kind of Dispose method where I can have it write to the EventLog or something if it fails? A "dying declaration" or something?
如果线程死了怎么“抓住”线程?是否有某种Dispose方法,我可以让它写入EventLog或其他东西,如果它失败?一个“垂死的宣言”还是什么?
-
How do I actively stop the thread? If I want it to stop running this background process, how do I kill it without having to bounce IIS?
如何主动停止线程?如果我希望它停止运行此后台进程,如何在不必退回IIS的情况下将其终止?
-
Is there anyway to start it again, independently of the HttpModule? (I'm guessing the answer to this is no...)
无论如何都要重新启动它,独立于HttpModule? (我猜这个问题的答案是否定的......)
Edit: Just to clarify, the intention is that my thread never goes away. It runs a function, then goes to sleep for a couple minutes, then wakes up and runs the function again. It's not like it's doing one task then ending.
编辑:只是为了澄清,意图是我的线程永远不会消失。它运行一个函数,然后进入睡眠状态几分钟,然后唤醒并再次运行该函数。它不像是在完成一项任务然后结束。
2 个解决方案
#1
6
From my experience, you can get this to work "good enough", but not perfect. I would recommend to implement your repeating tasks in a windows service. Depending on what the tasks do, the Windows Service maybe wouldn't even have to talk to the web application or vice versa, e. g. if both work with the same database. Otherwise you could still use e. g. WCF for communication.
根据我的经验,你可以让这个工作“足够好”,但并不完美。我建议在Windows服务中实现重复任务。根据任务的作用,Windows服务可能甚至不必与Web应用程序通信,反之亦然,例如, G。如果两者都使用相同的数据库。否则你仍然可以使用e。 G。 WCF用于通信。
The big advantage is: The windows service will start with the OS, you can easily configure, start and stop it using the control panel, you have built-in monitoring via Windows Event Log, you can update the background service and the web application independently etc.
最大的优点是:Windows服务将从操作系统开始,您可以使用控制面板轻松配置,启动和停止它,您可以通过Windows事件日志进行内置监控,您可以独立更新后台服务和Web应用程序等等
If this is not an option, e. g. because you are in a shared hosting environment, I would recommend the following:
如果这不是一个选项,e。 G。因为您处于共享托管环境中,我建议您使用以下内容:
- Start your background thread in Application_start (Global.asax), and store the thread reference in a static variable.
- 在Application_start(Global.asax)中启动后台线程,并将线程引用存储在静态变量中。
- Wrap every method called on your background thread with try/catch, because since .NET 2.0, every unhandled exception on a background thread will shut down the application. (It will be restarted on the next request, but it slows down the next request, kills all current sessions and caches, and of course no timer will be active until the next request.)
- 使用try / catch包装在后台线程上调用的每个方法,因为从.NET 2.0开始,后台线程上的每个未处理的异常都将关闭应用程序。 (它将在下一个请求中重新启动,但它会减慢下一个请求,终止所有当前会话和缓存,当然在下一个请求之前没有计时器将处于活动状态。)
- On every request (implemented has a HttpModule or in Global.asax again), check the Thread instance in the global variable (is it still != null, is the thread active and running etc.). If not, call the restart code. Use locking in the restart part to make sure that the thread will not be created twice at same time.
- 在每个请求(实现有HttpModule或再次在Global.asax中),检查全局变量中的Thread实例(它仍然是!= null,线程是否活动并正在运行等)。如果没有,请调用重启代码。在重启部分中使用锁定以确保不会同时创建两次线程。
Even then you can't be sure that your background thread is always running, if you don't have regular traffic around the clock. Also keep in mind that in a shared hosting environment it is very common to shut down application pools if there is no activity for a few hours. You could try to improve this by setting up a scheduled task on a client machine on your own network doing a light-weight HTTP request on your application every few minutes, just to ensure that your application is always running.
即使这样,如果您没有全天候的常规流量,也无法确定您的后台线程是否始终在运行。另请注意,在共享托管环境中,如果几小时内没有活动,则关闭应用程序池是很常见的。您可以尝试通过在您自己的网络上的客户端计算机上设置计划任务来每隔几分钟在您的应用程序上执行轻量级HTTP请求,以确保您的应用程序始终运行,从而改进这一点。
#2
9
When Jeff made *, he had a similiar issue.
当Jeff创建*时,他有一个类似的问题。
His solution was to use the cache expiration. You'd put something in the cache and then when it expires an event is fired in a non-user facing thread. In the event handler for the expiration, you stick some code in to re-add the item to the cache and do whatever housekeeping work needs to be done for your application
他的解决方案是使用缓存过期。你将一些东西放在缓存中,然后当它到期时,在非面向用户的线程中触发一个事件。在到期事件处理程序中,您可以粘贴一些代码以将项目重新添加到缓存中,并为您的应用程序执行任何需要管理的工作
Using this technique, your subquestions are easily answered:
使用此技术,您的子问题很容易回答:
- You check the item is still in cache.
- 您检查该项目是否仍在缓存中。
- If the item is not in cache, re-add it.
- 如果该项目不在缓存中,请重新添加。
- Remove the cache item from the cache.
- 从缓存中删除缓存项。
- Add the item back to the cache.
- 将项目添加回缓存。
You could make a small management page to configure these options.
您可以创建一个小型管理页面来配置这些选项。
This gives you a nice way to roughly time housekeeping processes in your web-application. It doesn't require a seperate Windows Service, which is a big win.
这为您提供了一种在Web应用程序中大致计算内务处理流程的好方法。它不需要单独的Windows服务,这是一个巨大的胜利。
#1
6
From my experience, you can get this to work "good enough", but not perfect. I would recommend to implement your repeating tasks in a windows service. Depending on what the tasks do, the Windows Service maybe wouldn't even have to talk to the web application or vice versa, e. g. if both work with the same database. Otherwise you could still use e. g. WCF for communication.
根据我的经验,你可以让这个工作“足够好”,但并不完美。我建议在Windows服务中实现重复任务。根据任务的作用,Windows服务可能甚至不必与Web应用程序通信,反之亦然,例如, G。如果两者都使用相同的数据库。否则你仍然可以使用e。 G。 WCF用于通信。
The big advantage is: The windows service will start with the OS, you can easily configure, start and stop it using the control panel, you have built-in monitoring via Windows Event Log, you can update the background service and the web application independently etc.
最大的优点是:Windows服务将从操作系统开始,您可以使用控制面板轻松配置,启动和停止它,您可以通过Windows事件日志进行内置监控,您可以独立更新后台服务和Web应用程序等等
If this is not an option, e. g. because you are in a shared hosting environment, I would recommend the following:
如果这不是一个选项,e。 G。因为您处于共享托管环境中,我建议您使用以下内容:
- Start your background thread in Application_start (Global.asax), and store the thread reference in a static variable.
- 在Application_start(Global.asax)中启动后台线程,并将线程引用存储在静态变量中。
- Wrap every method called on your background thread with try/catch, because since .NET 2.0, every unhandled exception on a background thread will shut down the application. (It will be restarted on the next request, but it slows down the next request, kills all current sessions and caches, and of course no timer will be active until the next request.)
- 使用try / catch包装在后台线程上调用的每个方法,因为从.NET 2.0开始,后台线程上的每个未处理的异常都将关闭应用程序。 (它将在下一个请求中重新启动,但它会减慢下一个请求,终止所有当前会话和缓存,当然在下一个请求之前没有计时器将处于活动状态。)
- On every request (implemented has a HttpModule or in Global.asax again), check the Thread instance in the global variable (is it still != null, is the thread active and running etc.). If not, call the restart code. Use locking in the restart part to make sure that the thread will not be created twice at same time.
- 在每个请求(实现有HttpModule或再次在Global.asax中),检查全局变量中的Thread实例(它仍然是!= null,线程是否活动并正在运行等)。如果没有,请调用重启代码。在重启部分中使用锁定以确保不会同时创建两次线程。
Even then you can't be sure that your background thread is always running, if you don't have regular traffic around the clock. Also keep in mind that in a shared hosting environment it is very common to shut down application pools if there is no activity for a few hours. You could try to improve this by setting up a scheduled task on a client machine on your own network doing a light-weight HTTP request on your application every few minutes, just to ensure that your application is always running.
即使这样,如果您没有全天候的常规流量,也无法确定您的后台线程是否始终在运行。另请注意,在共享托管环境中,如果几小时内没有活动,则关闭应用程序池是很常见的。您可以尝试通过在您自己的网络上的客户端计算机上设置计划任务来每隔几分钟在您的应用程序上执行轻量级HTTP请求,以确保您的应用程序始终运行,从而改进这一点。
#2
9
When Jeff made *, he had a similiar issue.
当Jeff创建*时,他有一个类似的问题。
His solution was to use the cache expiration. You'd put something in the cache and then when it expires an event is fired in a non-user facing thread. In the event handler for the expiration, you stick some code in to re-add the item to the cache and do whatever housekeeping work needs to be done for your application
他的解决方案是使用缓存过期。你将一些东西放在缓存中,然后当它到期时,在非面向用户的线程中触发一个事件。在到期事件处理程序中,您可以粘贴一些代码以将项目重新添加到缓存中,并为您的应用程序执行任何需要管理的工作
Using this technique, your subquestions are easily answered:
使用此技术,您的子问题很容易回答:
- You check the item is still in cache.
- 您检查该项目是否仍在缓存中。
- If the item is not in cache, re-add it.
- 如果该项目不在缓存中,请重新添加。
- Remove the cache item from the cache.
- 从缓存中删除缓存项。
- Add the item back to the cache.
- 将项目添加回缓存。
You could make a small management page to configure these options.
您可以创建一个小型管理页面来配置这些选项。
This gives you a nice way to roughly time housekeeping processes in your web-application. It doesn't require a seperate Windows Service, which is a big win.
这为您提供了一种在Web应用程序中大致计算内务处理流程的好方法。它不需要单独的Windows服务,这是一个巨大的胜利。