7

一个 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”之间的通信解决方案来协调要完成的长时间运行的工作。

4

2 回答 2

6

您可以在其自己的应用程序域中启动长时间运行的进程。

过去,当我需要此功能时,我会为此创建一个 Windows 服务。如果使用 WCF 连接它,它甚至根本不必在 IIS 机器上运行;您可以在网络上的任何机器上运行它。

于 2013-04-27T17:03:13.657 回答
4

您可能可以通过增加超时、使用不同的应用程序池或各种其他 hack 来完成这项工作,但您最好的选择是将长期运行的任务与 ui 和 asp.net 完全分离,并使用服务(不推荐)或轮询工作的计划任务;我个人会使用 aws sqs/sns 之类的东西来跟踪要完成的工作和 Windows 服务器中的计划任务,以任何有意义的频率检查待办事项。ui/asp.net 唯一需要做的就是记录需要做某事的事实,而不是实际去做。

这种基于消息的方法的另一个好处是,如果长时间运行的进程运行时间过长或工作过度,您将有机会添加更多工作任务或服务器来完成这些请求。

对于当前的问题,也许比您可以实施的更多,但需要考虑一些更好的长期解决方案。

于 2013-04-27T17:51:32.767 回答