【问题标题】:Correctly implement background process Thread in ASP.NET在 ASP.NET 中正确实现后台进程 Thread
【发布时间】:2014-10-11 06:07:35
【问题描述】:

我需要执行一个无限 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

【问题讨论】:

  • Clients.SetConnectionTimeStamp 有什么作用?它的目的是什么?您希望实现哪些特定功能?如果您想要一个高质量的答案,您需要提供此信息。
  • 这个最好用定时器。
  • @cadrell0 我想从集线器外部通过集线器进行广播github.com/SignalR/SignalR/wiki/Hubs
  • 如果您能够回答自己的问题,请将其发布为答案并将其标记为已接受。

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


【解决方案1】:

这是一篇旧帖子,但由于我正在为此搜索,我想报告一下,在 .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/

马里亚诺C

【讨论】:

    【解决方案2】:

    我发现这篇关于如何使用异步工作器的好文章,将尝试一下。 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

    【讨论】:

    • 小心 - 无限循环会吞噬你的处理器。此外,您必须确保不会意外启动这些事物的多个实例(这意味着进行一些多线程检查)。
    • @Cyborgx37 好吧,这就是我发布 OP 的原因,但不幸的是,在 SO 上有太多噪音......此外,如果您自己阅读过 OP,您就会知道该线程将是进入长时间睡眠,因此那里没有 CPU 问题。
    【解决方案3】:

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

    更新

    ASP.NET 不是为长时间运行的任务而设计的。它旨在快速响应 HTTP 请求。请参阅Cyborgx37's answerCan I use threads to carry out long-running jobs on IIS? 了解一些原因。

    更新

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

    【讨论】:

    • 第一个链接根本没有提供任何理由,第二个链接仅说明了服务器可能会选择在某个时候回收应用程序池的非常明显的担忧。我还没有听到一个有效的担忧,为什么这是一个“坏主意”。将某些内容纳入 Windows 服务,使您的应用程序更难以部署,这对我来说听起来是个坏主意。有人有真正的理由还是这仅仅是意识形态?
    • ...非常明显的担心服务器可能会选择在某个时候回收应用程序池这是一个相当大的问题...
    • 所有应用程序都会在某个时候出现故障,这不是 ASP.NET 独有的。您是否因为用户可以随时单击关闭按钮而反对在 WinForms 应用程序中执行后台作业?当服务器重新启动时,甚至 Windows 服务也需要关闭。这有什么不同?
    • 我根本没有争论,只是陈述我的观点:)。我认为这不一定是并行比较,因为在窗体和服务中,用户操作正在关闭应用程序,而 IIS 应用程序池可能由于用户控制之外的多种原因(生命周期、请求计数、内存使用情况等)而被回收)。
    【解决方案4】:

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

    要获得一个持续的进程,最好启动一个 Windows 服务。

    如果您采用“进行中”解决方案,这实际上取决于您在做什么。线程本身不会给您带来任何内存问题或死锁。您应该添加一个机制以在应用程序停止时停止您的线程。否则重启需要很长时间,因为它会等待你的线程停止。

    【讨论】:

    • 太棒了!我对他们被回收没有问题。这是要求之一。
    • 我同意同行。可以在这篇精彩的文章中找到解决方案和对这种危险的警告:haacked.com/archive/2011/10/16/…
    【解决方案5】:

    这取决于您在 while 循环中尝试完成的任务,但一般来说,在这种情况下,Windows Service 是最好的答案。安装 Windows 服务需要您在网络服务器上拥有管理员权限。

    对于无限循环,您最终会遇到很多关于 Windows 消息泵的问题。即使应用程序没有“做”任何事情,这也是使 Windows 应用程序保持活力的东西。没有它,程序就结束了。

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

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

    如果不能使用窗口服务,那么我认为最好的办法是设置一个带有自己的消息泵的单独线程,但这有点复杂。我从来没有在网络服务器上做过,但你也许可以启动一个应用程序。这将为您提供消息泵并允许您响应 Windows 事件等。唯一的问题是这将启动一个 Windows 应用程序(WPFWinForms),这在网络服务器。

    你想完成什么?有没有其他方法可以解决?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多