为什么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中终止!!更奇怪的是。什么好主意吗?
好了,经过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"
/>