Async Task <HttpResponseMessage> Get VS HttpResponseMessage Get

I need your help in the following. For almost a month I read about tasks and asynchronous mode.

I wanted to try to implement my new acquired knowledege in a simple app app project. I have the following methods, and both of them work as expected:

public HttpResponseMessage Get() { var data = _userServices.GetUsers(); return Request.CreateResponse(HttpStatusCode.OK, data); } public async Task<HttpResponseMessage> Get() { var data = _userServices.GetUsers(); return await Task<HttpResponseMessage>.Factory.StartNew(() => { return Request.CreateResponse(HttpStatusCode.OK, data); }); } 

So the question is. I tried using a violinist and see what is the difference between the two. The asynchronous process is a little faster, but beyond that, what are the real benefits of implementing something similar in web api?

+7
c # asynchronous asp.net-web-api async-await task
source share
3 answers

As others have pointed out, the async point on ASP.NET is that it frees up one of the threads in the ASP.NET thread stream. This works great for naturally-asynchronous operations, such as I / O-bound operations, because there are fewer threads on the server (there is no thread that โ€œprocessesโ€ the async operation, as I explain in my blog ). Thus, the main advantage of async on the server side is scalability.

However, you want to avoid Task.Run (and, even worse, Task.Factory.StartNew ) on ASP.NET. I call this "fake asynchrony" because they simply do synchronous / blocking work on the thread pool thread. They are useful in user interface applications where you want to push work away from the user interface thread so that the user interface remains responsive, but they should (almost) never be used in ASP.NET or other server applications.

Using Task.Run or Task.Factory.StartNew on ASP.NET will actually reduce your scalability. They will cause unnecessary thread switches. For longer operations, you can eliminate ASP.NET thread pool heuristics, as a result of which additional threads are created and then destroyed unnecessarily. I will explore these performance issues step by step in another blog post .

So, you need to think about what each action does, and whether any of them should be asynchronous. If so, then this action should be asynchronous. In your case:

 public HttpResponseMessage Get() { var data = _userServices.GetUsers(); return Request.CreateResponse(HttpStatusCode.OK, data); } 

What exactly does Request.CreateResponse do? It just creates a response object. That it is just a new fantasy. There is no I / O, and this is certainly not something that needs to be pushed into the background thread.

However, GetUsers much more interesting. It is more like reading data, which is based on I / O. If your backend can scale (for example, Azure SQL / Tables / etc), you should first look at this async , and as soon as your service exposes GetUsersAsync , this action can also become async :

 public async Task<HttpResponseMessage> Get() { var data = await _userServices.GetUsersAsync(); return Request.CreateResponse(HttpStatusCode.OK, data); } 
+21
source

This makes sense when a call comes up with large I / O operations. Yes, Async is faster because it frees up the request flow during the execution of operations. Thus, from the point of view of the web server, you are returning the stream back to the pool that the server can use for any future calls passing through.

So, for example, for. when you perform a search operation on an SQL server, you may want to do asynchronous work and see the performance benefits.

This is good for scalability, which includes multiple servers.

Thus, for example, when SearchRecordAsync sends its SQL to the database, it returns an incomplete task, and when the query falls into wait, it returns the query flow to the thread pool. Later, when the database operation is completed, the query flow is taken from the thread pool and used to continue the query.

Even if you are not using SQL operations, say you want to send an email to 10 people. In this case, asynchrony makes sense.

Async is also very convenient to show the progress of a long event. Thus, the user will still receive an active graphical interface, while the task runs in the background.

To understand, please look at this sample.

Here I am trying to initiate a task called send mail. Temporary I want to update the database while the background is performing the task of sending mail.

After updating the database, it waits for the completion of the mail sending task. However, with this approach, it is quite obvious that I can run the task in the background and still continue the original (main) thread.

 using System; using System.Threading; using System.Threading.Tasks; public class Program { public static void Main() { Console.WriteLine("Starting Send Mail Async Task"); Task task = new Task(SendMessage); task.Start(); Console.WriteLine("Update Database"); UpdateDatabase(); while (true) { // dummy wait for background send mail. if (task.Status == TaskStatus.RanToCompletion) { break; } } } public static async void SendMessage() { // Calls to TaskOfTResult_MethodAsync Task<bool> returnedTaskTResult = MailSenderAsync(); bool result = await returnedTaskTResult; if (result) { UpdateDatabase(); } Console.WriteLine("Mail Sent!"); } private static void UpdateDatabase() { for (var i = 1; i < 1000; i++) ; Console.WriteLine("Database Updated!"); } private static async Task<bool> MailSenderAsync() { Console.WriteLine("Send Mail Start."); for (var i = 1; i < 1000000000; i++) ; return true; } } 
+2
source

Using async on your server can greatly increase scalability, as it frees up the thread serving the request to handle other requests while the async operation is in async . For example, in a synchronous IO statement, the thread will be suspended and nothing will be done until the operation completes and is available to serve another request.

At the same time, using Task.Factory.StartNew starts another thread , so you do not get the benefits of scalability at all. Your source thread can be reused, but you have overloaded the work into another thread, so there is no net benefit. in fact there is the cost of switching to another thread, but this is minimal.

Truly asynchronous operations do not start the thread, and I would see if such an operation exists, or if it can be written for Request.CreateResponse . Then your code will be much more scalable. If not, you should take a synchronized approach.

0
source

All Articles