为什么ASP.. NET杀死了我的后台线程

本文关键字:我的 后台 线程 ASP NET 为什么 | 更新日期: 2023-09-27 18:02:04

我有以下代码在我的代码背后(aspx.cs):

protected void button1_Click(object sender, EventArgs e)
{
    new Thread(delegate() {
        try
        {
            Thread.Sleep(30000); //do nothing for 30 seconds
        }
        catch (Exception ex)
        {
            //I AWLAYS get a ThreadAbortException here
            //in about 1 second WHY!?!??!
        }
    }).Start();
}

ASP。. NET在请求结束时杀死所有子线程?

p。我预测会有很多"因为这不是最佳实践"的答案。我知道在windows服务中运行程序的最佳实践等。我只是好奇为什么在这个特定的代码中线程被杀死,因为没有"响应"。"重定向",没有"响应"。结束",没有池回收,没有iis重启等等(人们在ASP中重复"后台线程"的典型原因)。. NET是坏的"咒语)。

更新:事实证明它在ASP中工作得很好。净MVC ! !线程只在Web-Forms中终止!!更奇怪的是。什么好主意吗?

为什么ASP.. NET杀死了我的后台线程

好了,经过48小时的实验,我发现了以下结果:

1。在ASP中运行后台线程是可以的。净 _MVC_

如果你使用的是MVC模式-只要正常启动你的线程,它们不会在当前请求结束后被中止:

//MVC - works just fine
public ActionResult ThreadTest()
{
    new Thread(delegate() {
        try
        {
            System.Threading.Thread.Sleep(10000);
        }
        catch(Exception ex)
        {
            //no exception will be thrown
        }
    }).Start();
    return Content("ok");
}

2。对于Web-Forms -将BackgroundWorker与"Async"页面属性结合使用

我知道在webforms中你不能使用:

  • new Thread().Start(); //not working

  • ThreadPool.QueueUserWorkItem //not working

  • Action.BeginInvoke //not working

  • 一堆其他的东西-都不工作

你需要做的是:

1)在.aspx中将你的页面标记为"async"(这将告诉ASP。. NET从IAsyncHandler)继承页面

<%@ Page language="c#" Async="true" %>
2)在.aspx.cs中使用BackgroundWorker
protected void button1_Click(object sender, EventArgs e)
{
    var bg = new BackgroundWorker();
    bg.DoWork += delegate
    {
        try
        {
            Thread.Sleep(10000); //do nothing for 10 seconds
        }
        catch (Exception ex)
        {
            //no excpeiton is thrown
        }
    };
    bg.RunWorkerAsync();
}

3。如果你使用。net 4.5.2或更高版本-只需使用HostingEnvironment.QueueBackgroundWorkItem

" HostingEnvironment。QueueBackgroundWorkItem方法允许您安排一些小的后台工作项目。ASP。NET跟踪这些项目和防止IIS突然终止工作进程,直到所有的后台工作项已经完成。这个方法不能被调用在ASP之外。. NET管理的应用程序域。"

感谢@danny-tuppeny最后一个

响应结束通常会杀死一个线程,是的。如果您调用Response.End,您甚至可以看到IIS抛出ThreadAbortedException来立即终止线程。一般来说,您不应该在IIS中执行任何长时间运行的任务,尤其是在任务或后台线程上。有关为什么应该避免这种情况的更多信息,以及如何强制IIS处理长时间运行的操作(如果您确实需要),请查看以下链接:

关于IIS中长时间运行作业的堆栈溢出问题

asp.net中后台任务的危险性

净WebForms

提供另一个解决方案:您不需要设置您的页面与async属性。下面的代码可以正常工作:

new Thread
(
    delegate()
    {
        try
        {
            MyMethod(myVar);
        }
        catch (Exception ex)
        {
            // handle
        }
    }
)
{
    IsBackground = true
}.Start();

在这段代码中,IsBackground = true是用来防止线程在请求完成时被中止的。

. NET worker进程卸载虚拟应用程序,如果没有请求访问aspx/asmx页面,以节省IIS上的内存。

IIS正在踢出您的线程,因为它不是后台线程。

在IIS上有这个选项:

<processModel
enable="true"
timeout="Infinite"
idleTimeout="Infinite"
shutdownTimeout="0:00:05"
requestLimit="Infinite"
requestQueueLimit="5000"
restartQueueLimit="10"
memoryLimit="60"
webGarden="false"
cpuMask="0xffffffff"
userName="machine"
password="AutoGenerate"
logLevel="Errors"
clientConnectedCheck="0:00:05"
comAuthenticationLevel="Connect"
comImpersonationLevel="Impersonate"
responseRestartDeadlockInterval="00:09:00"
responseDeadlockInterval="00:03:00"
maxWorkerThreads="20"
maxIoThreads="20"
/>
相关文章: