Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
267 views
in Technique[技术] by (71.8m points)

c# - Why ASP.NET kills my background thread?

I have the following code in my codebehind (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();
}

Does ASP.NET kill all child threads when the request ends?

PS. I predict a lot of "because it's not best practice" answers. I know about best practices of running things in a windows service etc. I'm just curious WHY EXACTLY the thread is being killed in this particular code, given there's no "Response.Redirect", no "Response.End", no pool recycle, no IIS-restart etc etc (typical reasons people are repeating the "background thread in ASP.NET is bad" mantra).

UPDATE: As it turns out it works fine in ASP.NET MVC!!! The thread is aborted in Web-Forms only!! Which is even more weird. Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Ok, so after 48 hours of experimenting here's what I found:

1. It's fine to run background threads in ASP.NET _MVC_

If you're on MVC - just start your threads as normal, they won't be aborted after the current request ends:

//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. For Web-Forms - use BackgroundWorker in combination with "Async" page attribute

I learned that with webforms you can't use:

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

  • ThreadPool.QueueUserWorkItem //not working

  • Action.BeginInvoke //not working

  • A bunch of other things - all not working

Here's what you need to do:

1) Mark your page as "async" in .aspx (this will tell ASP.NET to inherit the page from IAsyncHandler)

<%@ Page language="c#" Async="true" %>

2) Use BackgroundWorker in .aspx.cs

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. If you're on .NET 4.5.2 or higher - simply use HostingEnvironment.QueueBackgroundWorkItem

"The HostingEnvironment.QueueBackgroundWorkItem method lets you schedule small background work items. ASP.NET tracks these items and prevents IIS from abruptly terminating the worker process until all background work items have completed. This method can't be called outside an ASP.NET managed app domain."

Kudos to @danny-tuppeny for this last one


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...