Async not working as I expected - c#

I've read all I can find on async programming in asp.net (c#). I've made sense of most of how it's supposed to work and when it should be used. Yet I find basic examples not working as I expect. Without Task.Run it doesn't seem to actually run asynchronously.
Can someone tell me what I'm missing in this example?
Say the code is like so
public async Task SubTask2()
{
LongRunningOperation2();
Response.Write("<br>------------------------ Finished -------------------------<br>");
}
private async Task<Boolean> LongRunningOperation1()
{
int counter;
for (counter = 0; counter < 50000; counter++)
{
Response.Write(counter + "<br>");
}
return await Task.FromResult<bool>(true);
}
private async Task<Boolean> LongRunningOperation2()
{
await LongRunningOperation1();
Response.Write("<br>------------------------ Long Task -------------------------<br>");
return true;
}
Shouldn't LongRunningOperation2() return to SubTask2() and print "finished" before or while writing out numbers? Instead it prints finished at the end. Using Task.Run works as expected but then I don't see the point of ever not using Task.Run

A design consideration of the async/await pattern is that sometimes code that has an async signature might return synchronously (immediately) - perhaps due to caching or local data buffering (reading data from a socket, perhaps, and having spare data left to consume from the buffer), or perhaps due to IoC etc providing a synchronous implementation of an asynchronous signature. In that scenario, the entire engine is designed to optimize by not doing anything as callbacks, but continuing to run synchronously. This is not an edge-case - recent C# updates have extended this by adding support for custom awaitables (in particular: ValueTask<T>) to make this even more efficient in the case when something completes with a synchronous but non-trivial result.
The purpose of async is to facilitate scenarios that have genuinely async components, freeing up the thread to do more useful things than waiting for an async operation to complete. It is not about parallelization.
In your case, all of your code is actually synchronous, so it continues to run synchronously all the way through.

First, you're missing await in SubTask2(), so it actually runs synchronously (waits for LongRunningOperation2() to finish).
Secondly, even with asynchronous execution, "finished" wouldn't be printed before LongRunningOperation2() finished it's work. The point of using it is to free the thread, so it can do some other work in the meantime (e.g. handle another request).

Related

Does Using Async Await Avoid Thread Exhaustion?

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.

Async method waiting for end?

I am rewriting some of my component management to use async start methods. Sadly it looks like a call to an async method WITHOUT await, still does await the result?
Can anyone enlighten me?
I am calling:
public async Task StartAsync() {
await DoStartProcessingAsync();
}
which in itself is calling a slow implementation of protected abstract Task DoStartProcessingAsync(); - slow because it dome some EF calls, then creates an appdomain etc. - takes "ages".
The actual call is done in the form:
x.StartAsync().Forget();
with "Forget" being a dummy function just to avoid the "no await" warning:
public static void Forget(this Task task) {
}
Sadly, this sequence - is waiting for the slow DoStartAsync method to complete, and I see no reason for that. I am quite old in C#, but quite new to async/await and I was under the impression that, unless I await for the async task - the method would complete. As such, I expected the call to StartAsyc().Forget() to return immediatly. INSTEAD stack trace shows the thread going all the way into the DoStartProcessingAsync() method without any async processing happening.
Anyone can enlighten me on my mistake?
What your trying to achieve here is a fire and forget type mechanism. So async/await isn't really what you want. Your not wanting to await anything.
These are designed to free up threads for long running processes. Right now your returning a Task using an await and then "forgetting" it. So why return the Task at all?
Your freeing up the thread for the long running process, but your also queuing a process that ultimately does nothing (this is adding overhead that you could likely do without).
Simply doing this, would probably make more sense:
public void StartAsync() {
Task.Run(() => DoStartProcessingAsync());
}
One thing to bear in mind is that your now using a ThreadPool thread not a UI thread (depending on what is actually calling this).

How to do asynchronous web calls from within asp.net

Lets say im within an ASP.NET application, WCF or web API, part of this applications job to is contact a 3rd party over the way. Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
Here is some code i have written:
public string GetSomeData()
{
Task<string> stuff = CallApiAsync();
return stuff.result; //does this block here?
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
I thought the idea was as follows but please correct any misconceptions.
The caller of CallApi can call the method and when it hits await there is a Task created which represents some work to be done asynchronously but that will take some time. At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request. Once the Task completes the await line wakes up and the code continues from there as if it was synchronous.
If this is the case why do i need to return a Task from my apimethod. The caller seems to have to call stuff.Result which implies that the task may not have finished and calling result could block ? Note i don't want to make the calling method async too as then the method that calls that would need to be async etc etc.
What is the order of event here in my code?
One other question is why did i need to set configureAwait to false? otherwise everything hangs.
Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
That's not possible. In order to be truly asynchronous, you must allow async to "grow" through the code as far as it needs to. What you're trying to do is block on an asynchronous call, which won't give you any benefit (you're freeing up a thread by using async, but then you're turning around and consuming a thread by using Result).
At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request.
Not quite. When an async method hits an await, it returns an incomplete Task to its caller. If the caller, in turn, awaits that task, then it returns an incomplete Task to its caller, etc. When the ASP.NET runtime receives an incomplete Task from your action/service method/whatever, then it releases the thread to the thread pool.
So, you do have to go "async all the way" to see the real benefit of async.
I have an async intro on my blog if you want a more gentle introduction, as well as an MSDN article on async best practices (one of which is: async all the way). I also have a blog post that describes the deadlock you were seeing.
The compiler handles a lot of the magic behind the async pattern for you, but syntactically, you have to tell it what you want it to do by providing a method prototype that says "ok, this is an asynchronous operation that can be awaited."
For this to happen, your method must return a Task or Task<T>.
Any Task can be awaited.
You should be VERY careful when using .Result and .Wait(), as they can block in some very unexpected circumstances, because the runtime may decide to execute your method synchronously.
You should say:
await CallApiAsync();
or, to actually take advantage of it:
Task stuff = CallApiAsync();
//More code that can happen independetly of "stuff"
await stuff;
In order to do that, your GetSomeData() function must also be marked as async, but it doesn't have to, itself, return a Task.
Finished copy of a working async version of your code:
public async string GetSomeData()
{
Task stuff = CallApiAsync();
return await stuff;
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
Honestly, if that's all the CallApiAsync function is ever going to do, you may as well inline it, though.

How to create your own asynchronous methods with async and await

I've been trying to find a solution for quite a long time that would show me how to create Asynchronous methods that do not use existing asynchronous code. IE someClass.ActionAsync()
I basically have been wanting to do something like
public string GetParsedData(string code){
Console.WriteLine("Starting parser");
var result = "";
foreach(var x in code.Split('\n')){
result += Encode(x);
}
return result;
}
So I understand I must return a Task, but I have found no information on how to await a lambda expression or any other advice on how to break this down. Oddly I think I found the answer from re-sharper giving me dated advice which I will post below.
A mandatory read that explains the root of all this discussion much better is Microsoft's "Task-based Asynchronous Pattern", including examples which help to learn it the "good way". The following summary is grabbed from there:
I was also newbie to this, but in summary what I have learned is that you need to distinguish between of IO-work vs. CPU-work. I was greatly inspired from #Stephen Cleary comment above.
For IO-bound intensive work you already have external xxxxAsync() functions available in .NET which is preferred mechanism by Microsoft. If your code includes calls to external await xxxxAsync(), then your function can be regarded as async as well. In this way, while the CPU is idle waiting for IO, the calling thread is not blocked.
For CPU-bound intensive work, without any external available xxxxAsync() function to call, there is an existing wrapper available in .NET to call your code: Task.Factory.StartNew(NET-4.0) or even easier and better Task.Run(NET-4.5), the latter being preferred by Microsoft in this case (*). If your code includes calls to await Task or returns a Task, then your function can be regarded as async as well. In this way, while the intensive task runs in the ThreadPool, the calling thread is not blocked.
(*) This mechanism is NOT thought to create async wrappers to your CPU-intensive functions. And specially NEVER do this if you are creating a library. Instead, its the other way around: you should call the existing sync CPU-intensive function from your code by using Task.Run.
Now the best example I have found for the WEB-UI thread blocked by a CPU-intensive operation is here. You can directly go there and skip the theory part.
So Resharper advised me to use TaskEx.Run (which is deprecated) and the proper answer appears to be Task.Run. I've found success rewriting the method as such,
public async Task<string> GetParsedData(string code){
Console.WriteLine("Starting parser");
var taskResult = await Task.Run(() =>
{
var result = "";
foreach(var x in code.Split('\n'))
{
result += Encode(x);
}
return result;
});
return taskResult;
}
Now I can use the await keyword on this method within other async methods as needed.

Wrapping synchronous code into asynchronous call

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
}
)
);

Categories

Resources