ASP.NET长时间运行的任务。线程正在中止异常

时间:2013-04-27 16:44:36

标签: c# asp.net asynchronous

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分钟a线程被中止异常被抛出。

有谁知道为什么会这样?或者如何防止它?

更多信息:

  • IIS标准配置。
  • 任务可以是任何内容,查询数据库和/或IO操作等。

更新:决定

谢谢大家的回复。现在我不知道哪个问题要标记为答案。所有这些都是有效的,并且可以解决这个问题。将等待今天并以最高票数回答答案,如果是平局我将选择第一个显示的答案,通常它们按最相关的顺序排列。

对于任何想要了解我选择的解决方案的人,再次由于时间限制,是改变IIS回收配置,但我认为是理想的解决方案,基于我的研究,当然还有下面的答案,是创建一个“工作服务”,并使用ASP.NET应用程序和新的“工作服务”之间的通信解决方案来协调长时间运行的工作。

2 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:4)

你有可能通过提高超时,使用不同的应用程序池或各种其他黑客来实现这一点,但你最好的选择是将长时间运行的任务与ui和asp.net彻底解耦,并使用服务(不推荐它)或轮询工作的计划任务;我个人会使用像aws sqs / sns这样的东西来跟踪要完成的工作,以及在Windows服务器中按照任何频率检查事情的计划任务。 ui / asp.net唯一需要做的就是记录需要完成某些事情的事实,而不是真正做到这一点。

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

或许可以为您的直接问题实施,但需要考虑更好的长期解决方案。