I don't even pretend to understand threading in C#, so I'm looking for a really simple explanation on threads - more specifically the StartNew() feature in .NET 4.
I use the following to call another method with a sort of fire-and-forget approach. I might do this when the web page needs to initiate a time-consuming process, but where the page doesn't really need to wait for the result. As I understand it, the DoSomething() method will run "asynchronously."
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
DoSomething();
});
The above code seems to work just as I want it to - although I have a sneaky suspicion that I'm not really using it for its intended purpose. I've also been caught-out using it in Console Applications that close before the DoSomething() method has run. I'm not sure why it works on web pages but not console apps - I'm assuming because the app pool continues to run even when the page has been unloaded.
The thing that really confuses me is that I've seen a lot of examples where they end such code with .Wait(). As I understand it, the .Wait() means that the rest of the code on this page will wait until the DoSomething() method has run... in which case - in my limited understanding - this seems to negate any benefit of using the StartNew() in the first place?
I hope somebody can help explain this in a way my simple little mind will understand! Perhaps you can also explain a better way of calling a method with a fire-and-forget approach? Many thanks!
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
DoSomething();
})
This will essentially offload the work onto the ThreadPool. A ThreadPool
thread is used once one is available (this means, it could actually be executed at different times, if the ThreadPool is filled).
By calling .Wait()
at the end, this will block until that task has finished executing. Essentially, it will not let the main thread to run until it's done,
and can lead to performance issues depending on how long DoSomething()
takes to execute.
A better approach is to use async/await
so that your application can continue to be responsive without tying up the main Thread
.
Also note that you should be using Task.Run
instead of StartNew
. Unless you need to provide other paramters (such as a cancellation token, schedule, etc.), Task.Run
is the default usage.
For example:
// fire and forget, this will run on a thread once one is available on the thread pool
Task.Run(()=>
{
DoSomething();
});
// fire and wait until exeuction has finished. this will block all activity until it is done
Task.Run(()=>
{
DoSomething();
}).Wait();
// fire and and wait until the task is completed but do not block the current thread.
private async void DoSomethingAsync()
{
await Task.Run(()=>
{
DoSomething();
});
// perform work after
}
NOTE: As VMAtm noted, "starting a task in ASP.NET app could be dangerous as it can be suspended with thread by IIS itself".
Why is it dangerous?
How to run tasks on ASP.NET app: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx