Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Task.Run considered bad practice in an ASP .NET MVC Web Application?

Background

We are currently developing a web application, which relies on ASP .NET MVC 5, Angular.JS 1.4, Web API 2 and Entity Framework 6. For scalability reasons, the web application heavility relies on the async/await pattern. Our domain requires some cpu-intensive calculations, which can takes some seconds (<10s). In the past some team members used Task.Run, in order to speed up the calculations.Since starting an extra thread inside ASP .NET MVC or Web API controllers is considered a bad practise (the thread is not known by the IIS, so not considered on AppDomain Recycle => See Stephen Cleary's blog post), they used ConfigureAwait(false).

Example

public async Task CalculateAsync(double param1, double param2) {     // CalculateSync is synchronous and cpu-intensive (<10s)     await Task.Run(() => this.CalculateSync(param1, param2))).ConfigureAwait(false); } 

Questions

  • Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
  • Does ConfigureAwait(false) really avoid the creation of an extra thread?
like image 808
Fabe Avatar asked Nov 17 '15 18:11

Fabe


People also ask

Should I use Task run C#?

You should use Task. Run , but not within any code you want to be reusable (i.e., library code). So you use Task.

What is Task ASP NET MVC?

The ASP.NET MVC 4 Controller class in combination . NET 4.5 enables you to write asynchronous action methods that return an object of type Task<ActionResult>. The . NET Framework 4 introduced an asynchronous programming concept referred to as a Task and ASP.NET MVC 4 supports Task.

Do you have to await Task run?

If it is some trivial operation that executes quickly, then you can just call it synchronously, without the need for await . But if it is a long-running operation, you may need to find a way to make it asynchronous.


2 Answers

Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?

Zero. None. In fact, you're hindering performance by spawning a new thread. Within the context of a web application, spawning a thread is not the same thing as running in the "background". This is due to the nature of a web request. When there's an incoming request, a thread is taken from the pool to service the request. Using async allows the thread to be returned before the end of the request, if and only if the thread is in a wait-state, i.e. idle. Spawning a thread to do work on, effectively idles the primary thread, allowing it to be returned to the pool, but you've still got an active thread. Returning the original thread to the pool does nothing at that point. Then, when the new thread finishes its work, you've got to request a main thread back from the pool, and finally return the response. The response cannot be returned until all work has completed, so whether you use 1 thread or a hundred, async or sync, the response cannot be returned until everything finishes. Therefore, using additional threads does nothing but add overhead.

Does ConfigureAwait(false) really avoid the creation of an extra thread?

No, or more appropriately, it's not about that. ConfigureAwait is just an optimization hint, and only determines whether the original context is maintained between thread jumps. Long and short, it has nothing to do with the creation of a thread, and at least in the context of an ASP.NET application, has negligible performance impact either way.

like image 120
Chris Pratt Avatar answered Sep 29 '22 00:09

Chris Pratt


Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?

No. And it doesn't matter whether it's CPU bound or not.

Task.Run offloads work to a ThreadPool thread. The web api request already uses a ThreadPool thread so you're just limiting scalability by offloading to another thread with no reason.

This is useful in UI apps, where the UI thread is a special single thread.

Does ConfigureAwait(false) really avoid the creation of an extra thread?

It doesn't affect thread creating in one way or another. All it does is configures whether to resume on the captured SynchronizationContext or not.

like image 35
i3arnon Avatar answered Sep 28 '22 22:09

i3arnon