I am trying to make use of the async/await feature of ASP.NET in my Web API project. I am not very sure whether it will make any difference in performance of my Web API service. Please find below the workflow and sample code from my application.
Work Flow:
UI Application → Web API endpoint(controller) → Call method in Web API service layer → Call another external web service. (Here we have the DB interactions, etc.)
Controller:
public async Task<IHttpActionResult> GetCountries()
{
var allCountrys = await CountryDataService.ReturnAllCountries();
if (allCountrys.Success)
{
return Ok(allCountrys.Domain);
}
return InternalServerError();
}
Service Layer:
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
return Task.FromResult(response);
}
I tested the above code and is working. But I am not sure whether it is the correct usage of async/await. Please share your thoughts.
I am not very sure whether it will make any difference in performance of my API.
Bear in mind that the primary benefit of asynchronous code on the server side is scalability. It won't magically make your requests run faster. I cover several "should I use async" considerations in my article on async ASP.NET.
I think your use case (calling other APIs) is well-suited for asynchronous code, just bear in mind that "asynchronous" does not mean "faster". The best approach is to first make your UI responsive and asynchronous; this will make your app feel faster even if it's slightly slower.
As far as the code goes, this is not asynchronous:
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
return Task.FromResult(response);
}
You'd need a truly asynchronous implementation to get the scalability benefits of async:
public async Task<BackOfficeResponse<List<Country>>> ReturnAllCountriesAsync()
{
return await _service.ProcessAsync<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}
Or (if your logic in this method really is just a pass-through):
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountriesAsync()
{
return _service.ProcessAsync<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}
Note that it's easier to work from the "inside out" rather than the "outside in" like this. In other words, don't start with an asynchronous controller action and then force downstream methods to be asynchronous. Instead, identify the naturally asynchronous operations (calling external APIs, database queries, etc), and make those asynchronous at the lowest level first (Service.ProcessAsync). Then let the async trickle up, making your controller actions asynchronous as the last step.
And under no circumstances should you use Task.Run in this scenario.
It is correct, but perhaps not useful.
As there is nothing to wait on – no calls to blocking APIs which could operate asynchronously – then you are setting up structures to track asynchronous operation (which has overhead) but then not making use of that capability.
For example, if the service layer was performing DB operations with Entity Framework which supports asynchronous calls:
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
using (db = myDBContext.Get()) {
var list = await db.Countries.Where(condition).ToListAsync();
return list;
}
}
You would allow the worker thread to do something else while the db was queried (and thus able to process another request).
Await tends to be something that needs to go all the way down: it is very hard to retro-fit into an existing system.
You are not leveraging async / await effectively because the request thread will be blocked while executing the synchronous method ReturnAllCountries()
The thread that is assigned to handle a request will be idly waiting while ReturnAllCountries() does it's work.
If you can implement ReturnAllCountries() to be asynchronous, then you would see scalability benefits. This is because the thread could be released back to the .NET thread pool to handle another request, while ReturnAllCountries() is executing. This would allow your service to have higher throughput, by utilizing threads more efficiently.
I would change your service layer to:
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
return Task.Run(() =>
{
return _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}
}
as you have it, you are still running your _service.Process call synchronously, and gaining very little or no benefit from awaiting it.
With this approach, you are wrapping the potentially slow call in a Task, starting it, and returning it to be awaited. Now you get the benefit of awaiting the Task.
Related
I am using async/await in MVC, but only when I have more than one task (WaitAll).
I understand that having only one task is good to have the UI free, in case of WPF or Windows Form, but does it make sense for MVC to have only one task and await for that?
I've seen it a lot in code, in MVC, but I don't get the advantages.
HTTP requests are handled by thread pool threads.
If you block a thread, it will not be able to do other work. Because the total number of threads is limited, this can led to the starvation of the thread pool and new requests will be denied - 503.
Using async code, the thread is released back to the thread pool, becoming available to handle new requests or the continuations of async code.
Like on client UIs, on the server, async code is all about responsiveness, not performance. Requests will take longer but your server will be able to handle more requests.
It depends on what you are trying to achieve. For instance, if you have multiple calls to multiple services you can always do it in a way that only the last call makes the rest of the system "wait".
You can optimise your code in a way that X asynchronously calls to services start (almost) at the same time without having to 'await' for one another.
public async Task RunSomethings()
{
var something1 = AsyncCall1();
var something2 = AsyncCall2();
var something3 = await AsyncCall3();
}
private async Task<Something1> AsyncCall1()
{
return await Something1();
}
private async Task<Something2> AsyncCall2()
{
return await Something2();
}
private async Task<Something3> AsyncCall3()
{
return await Something3();
}
I hope it helps.
Good question. Using asynchronous methods is all about using the resources effectively as well as give a good user experience. Any time you need to call on a resource that could take time to collect, it's good to use an async call.
This will do a few things. First, while a worker thread is waiting for data, it can be put on 'hold' so to speak, and that worker thread can do something else until the data is returned, an error is returned or the call just times out.
This will give you the second advantage. The interface the user is using to call the resource will be released, temporarily, to do other things. And overall, less server resources are consumed by idle processes.
I'd recommend watching the videos on this page here: https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async
It's probably the clearest explanation that can help leapfrog your learning on async.
This question already has answers here:
Wraping sync API into Async method
(2 answers)
Closed 1 year ago.
I read some posts and articles on the internet saying that I should not use async until my calls are IO (reading file, sending request, etc.). But if the calling API is actually an IO-related API and does not support async calls, should I wrap them with Task.Run()?
Say, if I have MVC server calling an external server via API to get data, but the API does not have async methods. Is there a benefit wrapping sync calls with async in such case?
As I understand, if not wrapping, then all calls to the API are sync and each call to my MVC app uses a thread from thread pool. In second case Task.Run() will queue my task onto thread pool, but releases main thread. Is released main thread considered to be benefit here, or it is not worth wrapping? Am I correct here at all?
EDIT
Ok, here are some more details as people requested.
I have a third party .NET assembly that I'm forced to use. I can't just call the web-service directly. It looks pretty much like this:
// the API (I not owner of it, can't change it):
public class Service {
/* everything is synchronous like this. but somewhere inside
it still makes HTTP requests to external server, so that's
kinda IO. just the lib is very old and doesn't provide async methods*/
public Data GetData(Paramters parameters);
}
// here comes my code.
// option 1. sync controller
public class MyController {
public ActionResult GetDataById(string id) {
var data = new Service().GetData(new Parameters{Id = id});
// process and return some result ...
}
}
// option 2. async controller
public class MyController {
public async ActionResult GetDataById(string id) {
var result = await Task.Run(() => new Service().GetData(new Parameters{Id = id}));
// process and return some result ...
}
}
So the question is, does it make sense to do option 2?
By wrapping into async, you may get the benefit of making parallel calls to the external server while the actual call would still remain sync , so it would be like multiple threads each waiting on response from external server. I have done this and it could be beneficial when you would like to handle the failures and then the application would not remain stuck in the calling threads.
Let's say if the API itself performs IO related tasks even then having a free main thread would benefit you if the user chooses to perform multiple tasks through the API you would benefit by having the main thread free rather than having it blocked on a single request.
We are troubleshooting the following performance issues on a .NET Core API endpoint:
The endpoint consistently returns in less than 500MS under minor load.
When we hit the endpoint from 3 browsers, with one request a second, it gets progressively slower (within a minute of adding a third browser making calls, response times drops to 50,000MS or worse.
Each additional browser adds threads used by the API, e.g. 40 threads base, 2nd browser hitting endpoint leads to 52 threads, third spikes to 70, and so on.
When one endpoint is loaded, the entire API returns slowly (all endpoints). This is my main reason for thinking "thread exhaustion", along with point #3.
The code currently looks like this:
public IActionResult GetPresentationByEvent(int eventid)
{
return Authorized(authDto =>
{
var eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
})
}
My theory is that return Authorized(authDto => holds a thread until it returns, leading to thread exhaustion.
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
}
}
Authorized is part of a third-party library, so I can't test this easily. Would like to know if this looks like a likely problem/solution.
Yes async await can reduce thread exhaustion. In a few words thread exhaustion arise when you generate more tasks than your ThreadPool can handle.
There are subtle specifities that you can check here : Thread starvation and queuing
The only thing that you have to keep in mind on your side is that you should never block inside a task. This implies calling asynchronous code with async await (and never using .Wait or .Result on a non finished task).
If you use some blocking code wich is not using the async await pattern you have to spawn it on a dedicated thread (not the task thread queue).
My theory is that return Authorized(authDto => holds a thread until it returns, leading to thread exhaustion.
Yes. You can easily tell whether a method is synchronous by looking at its return value. IActionResult is not an awaitable type, so this method will run synchronously.
Authorized is part of a third-party library, so I can't test this easily. Would like to know if this looks like a likely problem/solution.
Possibly. It all depends on whether Authorized can handle asynchronous delegates. If it can, then something like this would work:
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEventAsync(eventid);
return Ok(await eventList);
});
}
Note:
Tasks should be awaited before being passed to Ok or other helpers.
This introduces GetPresentationByEventAsync, assuming that your data-accessing code can be made asynchronous.
Since making GetPresentationByEvent asynchronous may take some work, it's worthwhile to investigate whether Authorized can take asynchronous delegates before attempting this.
Does Using Async Await Avoid Thread Exhaustion?
Yes and no. Asynchronous code (including async/await) does use fewer threads, since it avoids blocking threads. However, there is still a limit. Thread exhaustion is still possible since asynchronous code needs a free thread to complete. With asynchronous code, usually you can achieve an order of magnitude or two greater scalability before you run into scalability problems like thread exhaustion.
For more conceptual information on async ASP.NET, see this MSDN article.
In this scenario, system A needs to send a message to system B. The following code shows a sample of how this was accomplished:
public interface IExecutionStrategy
{
Task<Result> ExecuteMessage(Message message);
}
public class WcfExecutionStrategy
{
public async Task<Result> ExecuteMessage(Message message)
{
using (var client = new Client())
{
return await client.RunMessageOnServer(message);
}
}
}
public class MessageExecutor
{
private readonly IExecutionStrategy _strategy;
public MessageExecutor(IExecutionStrategy strategy)
{
_strategy = strategy;
}
public Task<Result> ExecuteMessage(Message msg)
{
// ....
// Do some common checks and code here
// ....
var result = await _strategy.ExecuteMessage(msg);
// ....
// Do some common cleanup and logging here
// .....
return result;
}
}
For reasons out of scope of this question we decided to switch from Wcf to using raw http streams, but we needed both side by side to gather metrics and test it out. So I created a new IExecutionStrategy implementation to handle this:
public class HttpclientExecutionStrategy
{
public async Task<Result> ExecuteMessage(Message message)
{
var request = CreateWebRequestmessage
var responseStream = await Task.Run(() =>
{
var webResponse = (HttpWebResponse)webRequest.GetResponse();
return webResponse.GetResponseStream();
}
return MessageStreamer.ReadResultFromStream(responseStream);
}
}
Essentially, the only way I could get this to be asynchronous was to wrap it in a Task.Run() so the web request was none blocking. (Note: due to unique stream manipulation requirements on both sending and receiving it is not straight forward to implement this is in HttpClient, and even if it's possible this fact is out of scope for this question).
We thought this was fine until we read Stephen Cleary's multiple blog posts about how Task.Run() is bad, both in library code and in Asp.Net applications. This makes perfect sense to me.
What doesn't make sense is how you actually implement a naturally asynchronous call if the third party library does not support an asynchronous movement. For example, if you were to use HttpClient.GetStreamAsync() what does that do that makes it better for asynchronous operations than Task.Run(() => HttpClient.GetStream()), and is there any way to remedy this for non-async third party libraries?
HttpClient.GetStreamAsync is a pure asynchronous method, which means no new threads will be introduced while making the call, and when using in combination with await, will yield control back to the caller until the IO request is done. This will scale well, as you actually free the ThreadPool thread that invoked the operation to so more work while the request is executing, so your server can actually process more requests in the meantime.
On the contrary, using a dedicated thread (sync over async) just to make a blocking IO request call will definitely not scale well, and might eventually cause a starvation if the execution time is long enough.
Edit
The truely asynchronous nature of the XXXAsync implementation comes from the network device driver supplying an asynchronous endpoint to the OS. Under the covers the WinHTTP (Thanks #Noseratio for the correction) library is used for the async operations. What that means is that an I/O Request Packet (IRP) is generated and passed to the device driver. Once the request is complete, a CPU interrupt will occur which will eventually cause the callback registered to be invoked. You can look at theses examples: Using WinInet HTTP functions in Full Asynchronous Mode or Windows with C++ - Asynchronous WinHTTP for asynchronous examples, and of course read the excellent There Is No Thread by Stephan Cleary. You can natively implement it yourself and wrap it in a managed wrapper.
Short Answer
Use async-await if the operation is truly asynchronous. If it's not, then don't pretend it is.
Long Answer
Asynchronous operations have only 2 real benefits: scalability and offloading. Scalability is mostly for the server-side while offloading is used for "special" threads (mostly GUI threads).
If you're dependent on a synchronous library and there's nothing you can do about, making it asynchronous using Task.Run doesn't improve scalability at all (and may in fact hinder it), and you're only left with offloading. async reduces resource usage only when the operation is inherently asynchronous, when there is no thread throughout the actual asynchronous part (network, disk, etc.)
If you're developing a rich-client application, go ahead and use "sync over async" with async-await. But for any other type of application, there's no reason to use async-await, and I would recommend against it.
I have a method in ASP.NET application, that consumes quite a lot of time to complete. A call to this method might occur up to 3 times during one user request, depending on the cache state and parameters that user provides. Each call takes about 1-2 seconds to complete. The method itself is synchronous call to the service and there is no possibility to override the implementation.
So the synchronous call to the service looks something like the following:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
And the usage of the method is (note, that call of method may happen more than once):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
I tried to change the implementation from my side to provide simultaneous work of this method, and here is what I came to so far.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Usage (part of "do other stuff" code runs simultaneously with the call to service):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
My question: Do I use the right approach to speed up the execution in ASP.NET application or am I doing unnecessary job trying to run synchronous code asynchronously?
Can anyone explain why the second approach is not an option in ASP.NET (if it is really not)?
Also, if such approach is applicable, do I need to call such method asynchronously if it is the only call we might perform at the moment (I have such case, when no other stuff there is to do while waiting for completion)?
Most of the articles in the net on this topic covers using async-await approach with the code, that already provides awaitable methods, but that's not my case. Here is the nice article describing my case, which doesn't describe the situation of parallel calls, declining the option to wrap sync call, but in my opinion my situation is exactly the occasion to do it.
It's important to make a distinction between two different types of concurrency. Asynchronous concurrency is when you have multiple asynchronous operations in flight (and since each operation is asynchronous, none of them are actually using a thread). Parallel concurrency is when you have multiple threads each doing a separate operation.
The first thing to do is re-evaluate this assumption:
The method itself is synchronous call to the service and there is no possibility to override the implementation.
If your "service" is a web service or anything else that is I/O-bound, then the best solution is to write an asynchronous API for it.
I'll proceed with the assumption that your "service" is a CPU-bound operation that must execute on the same machine as the web server.
If that's the case, then the next thing to evaluate is another assumption:
I need the request to execute faster.
Are you absolutely sure that's what you need to do? Are there any front-end changes you can make instead - e.g., start the request and allow the user to do other work while it's processing?
I'll proceed with the assumption that yes, you really do need to make the individual request execute faster.
In this case, you'll need to execute parallel code on your web server. This is most definitely not recommended in general because the parallel code will be using threads that ASP.NET may need to handle other requests, and by removing/adding threads it will throw the ASP.NET threadpool heuristics off. So, this decision does have an impact on your entire server.
When you use parallel code on ASP.NET, you are making the decision to really limit the scalability of your web app. You also may see a fair amount of thread churn, especially if your requests are bursty at all. I recommend only using parallel code on ASP.NET if you know that the number of simultaneous users will be quite low (i.e., not a public server).
So, if you get this far, and you're sure you want to do parallel processing on ASP.NET, then you have a couple of options.
One of the easier methods is to use Task.Run, very similar to your existing code. However, I do not recommend implementing a CalculateAsync method since that implies the processing is asynchronous (which it is not). Instead, use Task.Run at the point of the call:
private async Task MakeRequest()
{
// do some stuff
var task = Task.Run(() => Calculate(myInput));
// do other stuff
var myOutput = await task;
// some more stuff
}
Alternatively, if it works well with your code, you can use the Parallel type, i.e., Parallel.For, Parallel.ForEach, or Parallel.Invoke. The advantage to the Parallel code is that the request thread is used as one of the parallel threads, and then resumes executing in the thread context (there's less context switching than the async example):
private void MakeRequest()
{
Parallel.Invoke(() => Calculate(myInput1),
() => Calculate(myInput2),
() => Calculate(myInput3));
}
I do not recommend using Parallel LINQ (PLINQ) on ASP.NET at all.
I found that the following code can convert a Task to always run asynchronously
private static async Task<T> ForceAsync<T>(Func<Task<T>> func)
{
await Task.Yield();
return await func();
}
and I have used it in the following manner
await ForceAsync(() => AsyncTaskWithNoAwaits())
This will execute any Task asynchronously so you can combine them in WhenAll, WhenAny scenarios and other uses.
You could also simply add the Task.Yield() as the first line of your called code.
this is probably the easiest generic way in your case
return await new Task(
new Action(
delegate () {
// put your synchronous code here
}
)
);