【发布时间】:2013-04-21 16:45:00
【问题描述】:
一个 ASP.NET 3.5 webapp 必须启动几个需要几个小时才能完成的任务。由于显而易见的原因,启动这些任务的页面不能等待它们完成,也不会有人希望等待那么长时间才能获得响应,因此这些任务必须是异步的。
有一个 Helper 类来处理所有这些长时间运行的任务。目前调度和执行这些任务的主要方法如下:
public static bool ScheduleTask(TaskDescriptor task, Action action)
{
bool notAlreadyRunning = TasksAsync.TryAdd(task);
if (notAlreadyRunning)
{
Thread worker = null;
worker = new Thread(() =>
{
try { action(); }
catch(Exception e)
{
Log.LogException(e, "Worker");
}
TasksAsync.RemoveTask(task);
workers.Remove(worker);
});
workers.Add(worker);
worker.Start();
}
return notAlreadyRunning;
}
在早期的实现中,我们使用了ThreadPool.QueueUserWorkItem 方法,但结果始终相同:在 aprox. 20-30 分钟 Thread was being aborted 抛出异常。
有谁知道为什么会这样?或者如何预防?
更多信息:
- IIS 标准配置。
- 任务可以是任何东西,对数据库的查询和/或 IO 操作等。
更新:决定
感谢大家的回复。现在我不知道将哪个问题标记为答案。所有这些都是有效的,并且是解决此问题的可能方法。将等待今天并将投票最多的答案标记为答案,如果出现平局,我将选择第一个显示的答案,通常它们按最相关性排序。
对于任何想知道我选择的解决方案的人,同样由于时间限制,是更改 IIS 回收配置,但根据我的研究,当然还有下面的答案,我认为这是理想的解决方案,就是创建一个“Worker Service”,并使用 ASP.NET App 和新的“Worker Service”之间的通信解决方案来协调要完成的长时间运行的工作。
【问题讨论】:
-
您的 IIS AppPools/workers 是否回收?
-
IIS 配置是 IIS 7 的标准配置。所以是的,我猜。
-
我已经有一段时间没有深入了解 ASP.NET,但是如果内存可用,当工作进程回收时,它们可以停止线程。尝试禁用回收,看看这是否是线程中止的根源。 (如果是这种情况,不确定是否有解决方法;就像我说的,没有触及 那个 特定问题)
-
Phill Haack 在他的The Dangers of Implementing Recurring Background Tasks In ASP.NET 帖子中深入探讨了这个主题。希望对你有帮助
-
您可以按照以下线程禁用应用程序池回收:stackoverflow.com/questions/3156925/…,但我认为最好的方法是按照 Robert 的建议在不同的应用程序域上运行它。
标签: c# asp.net asynchronous