Throwing methods into a Task to avoid blocking the asp.net thread
I'm wondering if the following code has 开发者_StackOverflow中文版any gotcha's that I'm not aware of when running on a webserver. Reading through the excellent series http://reedcopsey.com/series/parallelism-in-net4/ I am unable to find anything that relates specifically to my question, same with the msdn, so I thought I'd bring it here.
Example call:
public ActionResult Index() {
ViewBag.Message = "Welcome to ASP.NET MVC!";
Task.Factory.StartNew(() => {
//This is some long completing task that I don't care about
//Say logging to the database or updating certain information
System.Threading.Thread.Sleep(10000);
});
return View();
}
ASP.Net supports asynchronous pages, see Asynchronous Pages in ASP.NET, but is a complicated programming model and does not bind at all with MVC. That being said, launching asynchronous tasks from a synchronous requests handler works up to a point:
- if the rate at which requests add new tasks exceeds the average rate of processing your process will crash eventually. The Tasks take up live memory and eventually they will fill up the in memory queues where they're stored and your will start getting failures to submit.
- .Net Taks are inherently unreliable as they lack a persistent storage, so all tasks that are submitted async must be threaded as 'abandonware', ie. if they never complete there is no loss to the application nor to the user making the request. If the task is important, then it must be submitted through a reliable mechanism that guarantees execution in the presence of failures, like the one presented in Asynchronous procedure execution.
One important thing in this case is to ensure that the code contained inside the task is wrapped in a try/catch block or any possible exceptions thrown in this thread will propagate. You also should ensure that in this long running task you are not accessing any of the Http Context members such as Request, Response, Session, ... as they might no longer be available by the time you access them.
Use new Thread
instead of Task.Factory.StartNew
. Task.Factory.StartNew
use thread from Threads Pool and if you will have many background tasks a Threads Pool will run out of threads and will degrade your web application. The requests will be queued and your web app eventually will die :)
You can test is your background work executed on Thread Pool using Thread.CurrentThread.IsThreadPoolThread
. If you get True then Thread Pool is used.
精彩评论