I have an MVC controller action that needs to make several web requests. So in an attempt to free this thread to handle other incoming web requests I wrote something like this: (NOTE: this is an over simplification of the real code)
public async Task<ViewResult> Index()
{
MyObj o = await Task.Factory.StartNew<MyObj>(() =>
{
WebClient c = new WebClient();
var res1 = c.DownloadString("...");
var res2 = c.DownloadString("..."); //Not shown but res1 required for this call.
return new MyObj(res1, res2);
}
return View(o);
}
My question is have I made things better or worse by spinning up a new thread to do this work. My intention is to free this .Net thread to handle other incoming requests while the network requests get made. But after looking at it seems to me I'm still making a .Net thread block, just maybe a different one from the thread pool instead of the original, so I'm really no better off. So is my suspicion correct and the above code making things worse?
The benefit of Task.Factory.StartNew() if it worked... is that it simplifies the work inside from having to be done all async. My question though is: Does doing it that way in fact free a thread for handling incoming web requests or is it still tying up the same number of threads from the thread pool?
StartNew(Action<Object>, Object, CancellationToken, TaskCreationOptions, TaskScheduler) Creates and starts a task for the specified action delegate, state, cancellation token, creation options and task scheduler.
Run(action) internally uses the default TaskScheduler , which means it always offloads a task to the thread pool. StartNew(action) , on the other hand, uses the scheduler of the current thread which may not use thread pool at all!
Yes, you are just blocking a different thread now.
If this was good, MVC would just wrap all action methods in a new task automatically.
To unblock threads you need async IO somewhere under the covers. The BCL usually provides this. If it says "async" on the box it usually is async IO.
That said, few web apps have the problem of running out of threads. The thread-pool starts tons of threads if necessary. Very few web apps are limited in throughput by the number of threads available. Do you really need to process 100s of concurrent requests? Can your backend services even handle this load? If any of these questions is answered by "no" you don't need async.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With