我在一个 MVC3 应用程序中有几个长时间运行的线程,它们旨在永远运行。
我遇到了一个问题,即 ThreadAbortException 被其他一些代码(不是我的)调用,我需要优雅地从中恢复并重新启动线程。目前,我们唯一的办法是回收 appDomain 的工作进程,这远非理想。
以下是有关此代码工作的一些详细信息:
此 MVC3 应用程序存在一个单例服务类。它必须是单例,因为它缓存数据。该服务负责向数据库发出请求。第三方库用于实际的数据库连接代码。
在这个单例类中,我们使用称为“QueryRequestors”的类的集合。这些类为对数据库的请求标识唯一的 package+stored_procedure 名称,以便我们可以对这些调用进行排队。这就是 QueryRequestor 类的目的:确保对同一个 package+stored_procedure 的调用(尽管它们可能有无限不同的参数)被排队,并且不会同时发生。这大大减轻了我们的数据库压力并提高了性能。
QueryRequestor 类使用内部 BlockingCollection 和内部 Task(线程)来监视其队列(阻塞集合)。当一个请求进入单例服务时,它会通过 package+stored_procedure 名称找到正确的 QueryRequestor 类,并将查询交给该类。查询被放入队列(阻塞收集)。QueryRequestor 的任务看到队列中有一个请求并调用数据库(现在涉及到第 3 方库)。当结果返回时,它们被缓存在单例服务中。Task 继续处理请求,直到阻塞集合为空,然后等待。
一旦 QueryRequestor 创建并启动并运行,我们永远不希望它死掉。每隔几分钟就会收到 24/7 的请求。如果服务中的缓存有数据,我们就使用它。当数据陈旧时,下一个请求会排队(并且后续的同时请求继续使用缓存,因为他们知道有人(另一个线程)已经在进行排队请求,这是有效的)。
所以这里的问题是当 QueryRequestor 类中的 Task 遇到 ThreadAbortException 时该怎么办。理想情况下,我想从中恢复并重新启动线程。或者,至少,处理 QueryRequestor(就我而言,它现在处于“损坏”状态)并重新开始。因为如果服务中不存在与 package+stored_procedure 名称匹配的下一个请求,则会创建一个新的 QueryRequestor。
我怀疑线程被第 3 方库杀死,但我不能确定。我所知道的是,我无处中止或试图杀死线程/任务。我希望它永远运行。但显然我们必须为这个异常准备好代码。当服务因为线程被中止而爆炸时,这很烦人。
处理这个问题的最佳方法是什么?我们怎样才能优雅地处理这个问题?