Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I offload work to other threads in ASP.NET?

I'm creating am ASP.NET web API where certain operations (synchronous, legacy code) might take some time (mostly IO limited, but some computationally intensive stuff too).

I understand that each incoming request is assigned a thread from the thread pool, but I'm a bit fuzzy on the rest. Is the request thread "special" in some way, warranting offloading work to other threads to avoid locking it up? Will offloading help with thread pool starvation and rejected requests? And if so, do I need to create an async wrapper for every potentially long-running function all the way down, or do I only need a single async wrapper at the highest level?

like image 876
cmeeren Avatar asked Mar 14 '18 10:03

cmeeren


1 Answers

Creating asynchronous wrappers for long-running tasks is pointless in an ASP.NET context and does nothing but hurt performance in several ways.

Running synchronous methods asynchronously on a thread pool thread makes sense when offloading a GUI thread or another special thread. In that case, the method should be invoked asynchronously by the caller on that special thread in whichever way the caller sees fit (using e.g. Task.Run, which should generally not be used in an implementation of an async method). In ASP.NET however, there's only thread pool threads, and none need to (and indeed should not) be offloaded in this manner for several reasons.

This is put most clearly by Stephen Cleary (who, after all, wrote the book on concurrency in C#) in the blog post Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation

That’s why one of the principles of ASP.NET is to avoid using thread pool threads (except for the request thread that ASP.NET gives you, of course). More to the point, this means that ASP.NET applications should avoid Task.Run.

[...]

In fact, the only place we really need an asynchronous calculation is when we call it from the UI thread.

The whole article is highly recommended and highlights various problems with offloading in ASP.NET.

Further reading:

  • This SO answer
  • Stephen Toub: Should I expose asynchronous wrappers for synchronous methods?
  • Ben Morris: Why you shouldn’t create asynchronous wrappers with Task.Run()
like image 97
cmeeren Avatar answered Nov 15 '22 07:11

cmeeren