我在MVC3应用程序中有几个长期运行的线程,它们打算永远运行。

我遇到了一个问题,其中其他一些代码(不是我的代码)正在调用ThreadAbortException,我需要从此恢复正常并重新启动线程。目前,我们唯一的办法是为appDomain回收工作进程,这远非理想。

以下是有关此代码的一些详细信息:

此MVC3应用程序存在一个单例服务类。它必须是单例,因为它缓存数据。该服务负责向数据库发出请求。第三方库用于实际的数据库连接代码。

在此单例类中,我们使用称为“QueryRequestors”的类的集合。这些类为数据库请求标识唯一的package + stored_procedure名称,以便我们可以将这些调用排队。这就是QueryRequestor类的目的:确保对同一package + stored_procedure的调用(尽管它们可能具有无限不同的参数)被排队,并且不会同时发生。这大大减轻了我们的数据库压力并提高了性能。

QueryRequestor类使用内部BlockingCollection和内部Task(线程)来监视其队列(blocking集合)。当请求进入单例服务时,它将通过package + stored_procedure名称找到正确的QueryRequestor类,并将查询移交给该类。查询被放入队列(阻塞收集)。 QueryRequestor的任务看到队列中有一个请求,并调用数据库(现在涉及到第三方库)。结果返回时,它们将缓存在单例服务中。任务继续处理请求,直到阻塞集合为空,然后等待。

创建QueryRequestor并使其启动并运行后,我们再也不会希望它消失。每隔几分钟就会有24/7的请求进入此服务。如果服务中的缓存中有数据,我们将使用它。当数据过时时,下一个请求将排队(随后的同时请求继续使用缓存,因为他们知道某个人(另一个线程)已经在发出排队请求,这很有效)。

因此,这里的问题是当QueryRequestor类中的Task遇到ThreadAbortException时该怎么办。理想情况下,我想从中恢复并重新启动线程。或者,至少,处置QueryRequestor(就我而言,它现在处于“中断”状态)并重新开始。因为如果服务中不存在与下一个与package + stored_procedure名称匹配的请求,它将创建一个新的QueryRequestor。

我怀疑该线程已被第3方库杀死,但是我不确定。我所知道的是,我无处可中止或试图杀死线程/任务。我希望它永远运行。但是很明显,我们必须为该异常准备好代码。当服务炸弹时非常令人讨厌,因为线程已中止。

处理此问题的最佳方法是什么?我们该如何优雅地处理呢?

最佳答案

您可以通过调用Thread.ResetAbort来停止重新抛出ThreadAbortException

请注意,异常的最常见情况是重定向调用,取消线程中止可能会导致执行请求代码的不良后果,否则由于杀死线程而将其忽略。与MVC(可以从 Controller 返回特殊的重定向结果)相比,WinForms(在代码和呈现之间的分离不太清楚)中这是一个常见问题。

10-05 18:26