Ale*_*lex 12 c# asp.net multithreading
我的代码隐藏(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();
}
Run Code Online (Sandbox Code Playgroud)
ASP.NET会在请求结束时终止所有子线程吗?
PS.我预测很多"因为这不是最佳实践"的答案.我知道在Windows服务中运行东西的最佳实践等.我只是好奇为什么线程在这个特定的代码中被杀死,因为没有"Response.Redirect",没有"Response.End",没有池回收没有IIS重启等等(人们重复"ASP.NET中的后台线程是坏的"口头禅的典型原因).
更新:事实证明它在ASP.NET MVC中工作正常!线程仅在Web表单中中止!哪个更奇怪.有任何想法吗?
Ale*_*lex 18
好的,经过48小时的实验,我发现了这些:
如果您使用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");
}
Run Code Online (Sandbox Code Playgroud)
我了解到使用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" %>
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
HostingEnvironment.QueueBackgroundWorkItem"HostingEnvironment.QueueBackgroundWorkItem方法允许您安排小的后台工作项.ASP.NET跟踪这些项目并阻止IIS突然终止工作进程,直到所有后台工作项都完成.此方法无法在ASP.NET托管之外调用应用域名."
感谢@ danny-tuppeny最后一个
响应的结束通常会杀死一个线程,是的.如果你打电话,Response.End你甚至可以看到IIS抛出一个ThreadAbortedException立即终止线程.通常,您不应该在IIS中执行任何长时间运行的任务,尤其是在任务或后台线程上.有关为什么要避免这种情况的更多信息,以及如何强制IIS处理长时间运行的操作(如果你真的必须),请查看以下链接:
| 归档时间: |
|
| 查看次数: |
7484 次 |
| 最近记录: |