Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous methods of ApiController -- what's the profit? When to use?

Tags:

(This probably duplicates the question ASP.NET MVC4 Async controller - Why to use?, but about webapi, and I do not agree with answers in there)

Suppose I have a long running SQL request. Its data should be than serialized to JSON and sent to browser (as a response for xhr request). Sample code:

public class DataController : ApiController {     public Task<Data> Get()     {         return LoadDataAsync(); // Load data asynchronously?     } } 

What actually happens when I do $.getJson('api/data', ...) (see this poster http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster.pdf):

  1. [IIS] Request is accepted by IIS.
  2. [IIS] IIS waits for one thread [THREAD] from the managed pool (http://msdn.microsoft.com/en-us/library/0ka9477y(v=vs.110).aspx) and starts work in it.
  3. [THREAD] Webapi Creates new DataController object in that thread, and other classes.
  4. [THREAD] Uses task-parallel lib to start a sql-query in [THREAD2]
  5. [THREAD] goes back to managed pool, ready for other processing
  6. [THREAD2] works with sql driver, reads data as it ready and invokes [THREAD3] to reply for xhr request
  7. [THREAD3] sends response.

Please, feel free to correct me, if there's something wrong.

In the question above, they say, the point and profit is, that [THREAD2] is not from The Managed Pool, however MSDN article (link above) says that

By default, parallel library types like Task and Task<TResult> use thread pool threads to run tasks.

So I make a conclusion, that all THREE THREADS are from managed pool.

Furthermore, if I used synchronous method, I would still keep my server responsive, using only one thread (from the precious thread pool).

So, what's the actual point of swapping from 1 thread to 3 threads? Why not just maximize threads in thread pool?

Are there any clearly useful ways of using async controllers?

like image 644
Rustem Mustafin Avatar asked Nov 12 '13 16:11

Rustem Mustafin


People also ask

When would you use asynchronous actions?

Asynchronous actions are best when your method is I/O, network-bound, or long-running and parallelizable. Another benefit of an asynchronous action is that it can be more easily canceled by the user than a synchronous request.

What are the benefits of asynchronous code?

Asynchronous functions Front end applications benefit from its use because it enhances the flow of an application. Backend processes may use asynchronous functions to run many tasks or make lots of network calls. In the backend, asynchronous programming allows the computer to do more, faster.

What is the primary purpose of using an asynchronous controller action?

You can use asynchronous action methods for long-running, non-CPU bound requests. This avoids blocking the Web server from performing work while the request is being processed.

Does asynchronous programming improve performance?

Using asynchronous code does not give an increased performance on a development machine. The reason is that there is not enough load to see the overall benefit. But for a production environment, it can process more requests.


2 Answers

I think the key misunderstanding is around how async tasks work. I have an async intro on my blog that may help.

In particular, a Task returned by an async method does not run any code. Rather, it is just a convenient way to notify callers of the result of that method. The MSDN docs you quoted only apply to tasks that actually run code, e.g., Task.Run.

BTW, the poster you referenced has nothing to do with threads. Here's what happens in an async database request (slightly simplified):

  1. Request is accepted by IIS and passed to ASP.NET.
  2. ASP.NET takes one of its thread pool threads and assigns it to that request.
  3. WebApi creates DataController etc.
  4. The controller action starts an asynchronous SQL query.
  5. The request thread returns to the thread pool. There are now no threads processing the request.
  6. When the result arrives from the SQL server, a thread pool thread reads the response.
  7. That thread pool thread notifies the request that it is ready to continue processing.
  8. Since ASP.NET knows that no other threads are handling that request, it just assigns that same thread the request so it can finish it off directly.

If you want some proof-of-concept code, I have an old Gist that artificially restricts the ASP.NET thread pool to the number of cores (which is its minimum setting) and then does N+1 synchronous and asynchronous requests. That code just does a delay for a second instead of contacting a SQL server, but the general principle is the same.

like image 78
Stephen Cleary Avatar answered Sep 18 '22 03:09

Stephen Cleary


The profit of asynchronous actions is that while the controller is waiting for the sql query to finish no threads are allocated for this request, while if you used a synchronous method a thread would be locked up in the execution of this method from the start to end of that method. While SQL server is doing its job the thread isn't doing anything but waiting. If you use asynchronous methods this same thread can respond to other requests while SQL server is doing its thing.

I believe your steps are wrong at step 4, I don't think it will create a new thread to do the SQL query. At 6 there isn't created a new thread, it is just one of the available threads that will be used to continue from where the first thread left off. The thread at 6 could be the same as started the async operation.

like image 23
Olav Nybø Avatar answered Sep 21 '22 03:09

Olav Nybø