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

我的代码隐藏(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会在请求结束时终止所有子线程吗?

PS。 我预测很多“因为这不是最佳实践”的答案。 我知道在Windows服务中运行东西的最佳实践等。我只是好奇为什么线程在这个特定代码中被杀死,因为没有“Response.Redirect”,没有“Response.End”,没有池回收,没有IIS重启等等(人们重复“ASP.NET中的后台线程是坏的”口头禅的典型原因)。

更新:事实certificate它在ASP.NET MVC中工作正常 ! 线程仅在Web表单中中止! 哪个更奇怪。 有任何想法吗?

好吧,经过48小时的实验,我发现了这些:

1.在ASP.NET _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表单 – 将BackgroundWorker与“Async”页面属性结合使用

我了解到使用webforms你无法使用:

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

  • ThreadPool.QueueUserWorkItem //not working

  • Action.BeginInvoke //not working

  • 一堆其他的东西 – 都没有用

这是你需要做的:

1)在.aspx中将您的页面标记为“async”(这将告诉ASP.NET从IAsyncHandlerinheritance该页面)

 <%@ 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中后台任务的危险

ASP.NET WebForms

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

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

在此代码中, IsBackground = true是在请求完成时阻止线程中止的原因。

如果没有请求访问aspx / asmx页面以在IIS上保存内存,ASP.NET工作进程将卸载虚拟应用程序。

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

在IIS上有这个选项: