在ASP.NET中正确实现后台进程Thread

时间:2012-06-01 14:49:19

标签: asp.net asp.net-mvc multithreading

我需要执行一个无限的while循环,并希望在global.asax中启动执行。 我的问题是我该怎么做?我应该开始新线程还是应该使用Async和Task或其他任何东西?在while循环中我需要await TaskEx.Delay(5000);

我该怎么做才能阻止任何其他进程并且不会造成内存泄漏?

我使用的是VS10,AsyncCTP3,MVC4

修改

 public void SignalRConnectionRecovery()
        {
            while (true)
            {
                Clients.SetConnectionTimeStamp(DateTime.UtcNow.ToString());
                await TaskEx.Delay(5000);
            }
        }

只要应用程序可用,我需要做的就是全局运行它作为单例实例。

修改:解决

这是Global.asax

中的最终解决方案
protected void Application_Start()
{
    Thread signalRConnectionRecovery = new Thread(SignalRConnectionRecovery);
    signalRConnectionRecovery.IsBackground = true;
    signalRConnectionRecovery.Start();

    Application["SignalRConnectionRecovery"] = signalRConnectionRecovery;
}


protected void Application_End()
{
    try
    {
        Thread signalRConnectionRecovery = (Thread)Application["SignalRConnectionRecovery"];
        if (signalRConnectionRecovery != null && signalRConnectionRecovery.IsAlive)
        {
            signalRConnectionRecovery.Abort();
        }
    }
    catch
    {
            ///
    }
}

我发现这篇关于如何使用异步工作者的好文章:http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx

这个: http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6

但我觉得我的需求很完美: http://forums.asp.net/t/1433665.aspx/1

5 个答案:

答案 0 :(得分:15)

ASP.NET不是为处理这种要求而设计的。如果你需要不断运行的东西,你最好创建一个Windows服务。

更新

ASP.NET不适用于长时间运行的任务。它旨在快速响应HTTP请求。有以下原因,请参阅Cyborgx37's answerCan I use threads to carry out long-running jobs on IIS?

更新

既然你最后提到你正在使用SignalR,我看到你正在尝试在ASP.NET中托管SignalR,对吗?我认为你的方法是错误的,请参阅NuGet package上引用的示例project wiki。此示例使用IAsyncHttpHandler来管理任务。

答案 1 :(得分:10)

你可以在你的global.asax中启动一个线程,但它只会运行直到你的asp.net进程被回收。这将至少每天发生一次,或者当没有人使用您的网站时。如果进程被回收,那么线程重新启动的唯一方法就是在您的站点上点击时。所以线程没有继续运行。

要获得继续进程,最好启动Windows服务。

如果您执行“进行中”解决方案,它实际上取决于您正在做什么。线程本身不会导致内存或死锁问题。你应该添加一个meganism来停止你的线程在应用程序停止时。否则重启将花费很长时间,因为它会等待你的线程停止。

答案 2 :(得分:3)

这是一篇很老的帖子,但是当我正在搜索这篇文章时,我想报告一下,在.NET 4.5.2中,有一种使用QueueBackgroundWorkItem的本地方法。

看一下这篇文章:https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/

MarianoC

答案 3 :(得分:2)

这取决于你在while循环中想要完成的事情,但总的来说这是Windows Service是最佳答案的情况。安装Windows服务将要求您具有Web服务器的管理员权限。

对于无限循环,您最终会遇到很多关于Windows消息泵的问题。即使应用程序没有“正在”执行任何操作,这也可以使Windows应用程序保持活动状态。没有它,程序就会结束。

无限循环的问题是应用程序被“做”某事,这会阻止其他应用程序(或线程)“做”他们的事情。有一些解决方法,例如Windows窗体中的DoEvents,但它们在响应性和资源管理方面都有一些严重的缺点。 (可以在小型LOB应用程序上接受,也可能不在Web服务器上。)即使while循环位于单独的线程上,它也会耗尽所有可用的处理能力。

Asynchronus编程实际上是为长时间运行的进程设计的,例如等待数据库返回结果或等待打印机联机。在这些情况下,外部过程需要很长时间,而不是一个循环。

如果无法使用Window Service,那么我认为您最好的选择是使用自己的消息泵设置一个单独的线程,但它有点复杂。我从未在Web服务器上完成它,但您可以启动应用程序。这将为您提供消息泵,并允许您响应Windows事件等。唯一的问题是这将启动Windows应用程序(WPFWinForms),这可能不会在网络服务器上是可取的。

你想要完成什么?还有另外一种方法吗?

答案 4 :(得分:1)