Trying to understand this async await conundrum - c#

I have a specific example of async await with a problem that I can't wrap my head around.
public async Task<bool> DoStuff()
{
//do some stuff
return await DoSomeOtherStuff();
}
public Task<bool> SomeOtherMethod()
{
return DoStuff();
}
public bool SomeSynchronousMethod()
{
//this method does a lot of stuff, but most importantly, it calls SomeOtherMethod without awaiting it
SomeOtherMethod();
/// some more stuff
//imagine DoStuff sends an e-mail. Sometimes the e-mail will be sent without problem, sometimes it won't be.
return true;
}
The method DoStuff() awaits an async task. The method SomeOtherMethod doesn't always work if I do not await the result. In my mind, I thought if the method DoStuff() awaits the result, I will always receive a valid result, even if I don't await my SomeOtherMethod() result, but it does not seem to work like that.
(I am sure, because adding the extra await whenever I call SomeOtherMethod actually solved a pretty weird bug).
Is this right in what I'm seeing? What concept am I missing that would explain why this does not work as I would have expected?

In my mind, I thought if the method DoStuff() awaits the result, I will always receive a valid result, even if I don't await my SomeOtherMethod() result, but it does not seem to work like that.
That's an incorrect understanding. DoStuff() might return immediately to the calling method, but the Task it returns is guaranteed not to complete until the Task returned from DoSomeOtherStuff completes. If the task returned from DoStuff() is not awaited, execution will continue without waiting for that Task to complete.
You haven't provided many details about the environment you're running in, but let's imagine SomeSynchronousMethod gets executed by a command line application, which then exits. If you don't await the task, then the application may exit before the asynchronous work happening in DoSomeOtherStuff is able to complete. So, for example, an HTTP or SMTP communication that's still in progress will suddenly stop and won't complete.
There are a lot of nitty-gritty details about how async/await and Tasks work: more than I can address in a StackOverflow answer. But the key principle that emerges from those details is that you should never let a Task go unawaited. If you want certain tasks to be accomplished in the background, but guarantee that they get completed before the app exits, you could add them to a collection and then have the application's main method await all those tasks before it exits. Different types of applications have different patterns for implementing background tasks like this.

Related

Is a method always async if it has the key word "async" and "await"? [duplicate]

I've been trying to understand async/await and Task in C# but have been failing spectacularly despite watching youtube videos, reading documentation and following a pluralsight course.
I was hoping someone might be able to help answer these slightly abstract questions to help my brain out.
1.Why do they say that async/await enables an 'asynchonrous' method when the async keyword on it's own does nothing and the await keyword adds a suspension point? Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
2.Apparently you are not supposed to use async void except for event handlers, so how do you call an async method normally? It seems that in order to call an async method by using the await keyword, the method/class that is calling it itself needs to be marked as async. All the examples I've seen have 'initiated' an async void method with an event handler. How would you 'escape' this wrapping of async/await to run the method?
3.
public async Task SaveScreenshot(string filename, IWebDriver driver)
{
var screenshot = driver.TakeScreenshot();
await Task.Run(() =>
{
Thread.Sleep(2000);
screenshot.SaveAsFile(filename, ScreenshotImageFormat.Bmp);
Console.WriteLine("Screenshot saved");
});
Console.WriteLine("End of method");
}
Relating back to 1. this looks like a synchronous method. Execution pauses when it gets to Task.Run, therefore Console.WriteLine("End of method"); will not be executed until the task is finished. Maybe the whole method itself will be executed asynchronously at the point it is triggered in the code? But relating back to 2, you need to call this with an await otherwise you get the message 'Because this call is not awaited..' therefore adding an await will cause that execution point to be synchronous and so on and so.
Any help understanding this would be much appreciated.
Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
No, the word you're thinking of is "sequential", not "synchronous". await results in asynchronous sequential code. "Sequential" meaning "one at a time"; "synchronous" meaning "blocking until completed".
how do you call an async method normally?
Using await.
How would you 'escape' this wrapping of async/await to run the method?
Ideally, you don't. You go async all the way. Modern frameworks (including ASP.NET MVC, Azure Functions / WebJobs, NUnit / xUnit / MSTest, etc) all allow you to have entry points that return Task. Less-modern frameworks (including WinForms, WPF, Xamarin Forms, ASP.NET WebForms, etc) all allow async void entry points.
So, ideally you do not call asynchronous code from synchronous code. This makes sense if you think about what asynchronous code is: the entire point of it is to not block the calling thread, so if you block the calling thread on asynchronous code, then you lose all the benefits of asynchronous code in the first place.
That said, there are rare situations where you do need to treat the code synchronously. E.g., if you are in the middle of a transition to async, or if you are constrained by a library/framework that is forcing your code to be synchronous and won't work with async void. In that case, you can employ one of the hacks in my article on brownfield async.
Your understanding is pretty good :). The main point you seem to be missing is that "asynchronous" methods in .NET mean methods that can stop execution without blocking the calling thread.
As you pointed out in (1), the async keyword basically enables the use of await and requires the return type to be void or Task/Task<T>. await just instructs the current method to suspend execution until the task is complete.
What you are missing here is that it suspends just the current method. It does not block the thread the method was executing on. This is important in cases like the UI thread of a WPF application. Suspend method execution and everything keeps running, block the thread and the application stops responding.
You usually want your async calls to go all the way to the top (like an event handler), this allows the most flexibility and prevents deadlock situations. However; you can wait for a Task returning method to complete with Wait:
someAsyncMethod.Wait()
Or get the return value:
var result = someAsyncMethod.Result;
Note that both of these are synchronous and block the calling thread. Doing this can cause deadlock if the async task is waiting for some other work on the calling thread to complete.
The above should answer your question in (3); the method itself appears to execute synchronously (this is the magic of await/async) but the task doesn't block the calling thread.
It is asynchronous because you don't have to wait the method to return. In your code, you may call the async method and save the task in a variable. Continue doing something else. Later, when the method result is needed, you await the response (task).
// Synchronous method.
static void Main(string[] args)
{
// Call async methods, but don't await them until needed.
Task<string> task1 = DoAsync();
Task<string> task2 = DoAsync();
Task<string> task3 = DoAsync();
// Do other stuff.
// Now, it is time to await the async methods to finish.
Task.WaitAll(task1, task2, task3);
// Do something with the results.
Console.WriteLine(task1.Result);
Console.ReadKey();
}
private static async Task<string> DoAsync()
{
Console.WriteLine("Started");
await Task.Delay(3000);
Console.WriteLine("Finished");
return "Success";
}
// Output:
// Started
// Started
// Started
// Finished
// Finished
// Finished
// Success

Does the following code sequence make sense in C#

I haven't used async/await very often and I'm not fully comfortable with them. I am trying to make an operation that is synchronous to be run asynchronously. Can you tell me if the following code snippet makes sense:
public static async Task<string> FileVersionAsync(string localFilePath)
{
FileVersionInfo versionInfo;
try
{
versionInfo = await Task.FromResult(FileVersionInfo.GetVersionInfo(localFilePath));
}
catch (SecurityException)
{
return "File Version Checker does not have permission to read file version";
}
catch (FileNotFoundException)
{
return "Unable to find configured file";
}
if (versionInfo.FileVersion == null)
return "N/A";
return versionInfo.FileVersion;
}
Adding Task, await and async do not make something asynchronous; they merely provide the plumbing to work with asynchronous code when it happens. In your example: it never happens asynchronously, so all you are doing is adding plumbing overhead for no benefit.
The compiler will generate a ton of extra code that will turn out to never be hit, because when it gets to the await it'll discover that the task is already complete, and will simply continue on the existing thread.
To actually be asynchronous, you need ... something that is async. This could be external IO, or could be something threading related - but note that simply jumping to another thread doesn't buy you anything: it just adds a context switch.
If there was a FileVersionInfo.GetVersionInfoAsync method, what you are doing might be worthwhile.
No it does not make sense.
The only reason to make your function async is if somewhere inside it awaits other functions that are async. In fact your compiler warns you if you forget to await somewhere.
The async-await syntax was invented as a replacement for other task functions like Task.ContinueWith, Task.FromResult, Task.FromException etc.
In this interview Eric Lippert compared async-await with a cook who has to prepare breakfast Search somewhere in the middle for async-await.
If a cook has to prepare breakfase he starts to boil water. But instead of waiting for the water to cook, he starts slicing bread, and do other things. Only after he has nothing to do anymore he starts waiting idly for the water to boil after which he makes the tea.
Similarly: if a program has to wait for an external process to perform a request, like a database query, write data to a file, get information from the internet etc. async-await makes sure that your thread doesn't wait idly. Instead your thread goes up its call stack to see if one of the callers can continue working without the result from the other process.
You'll see this in the following code:
public async Task<string> ReadTextFile()
{
StreamReader txtReader = File.OpenText(...);
// read the complete text file; don't wait until finished yet
Task<String> taskTxt = txtReader.ReadToEndAsync();
// as we didn't use await, we can continue processing:
DoSomething();
// now we need the result from the read action: await for it
// the result of await Task<TResult> is the TResult:
string importedTxt = await taskTxt;
return importedTxt;
}
Some guidelines for async-await:
Only use async-await if you call at least one other async function
instead of void return Task, instead of TResult return Task<TResult>
Only exception: the async event handler: this async function returns void
The return of await Task is void; the return of await Task<TResult> is TResult
If you don't need the result of an async function right now, and if you can do something meaningful while the task is processing: start the task by calling the async function, but don't await for it. Only await when you need the result
.
public async void Button_Clicked(object sender, EventArgs e)
{
// indicate you will do something time consuming:
this.ProgressBar1.Visible = true;
await DoSomethingTimeconsumingAsync(...);
// finished:
this.progressBar1.Visible = false;
}
This will make sure that whenever your thread has to wait something, it can do other things, and thus your GUI remains responsive.
No. There appears to be absolutely no need to make this method async, because Task.FromResult is ready immediately.

Making async method properly

I googled a lot and for the moment the only async implementation I found (including MSDN site) is the following:
public async void Foo()
{
...
await StreamReader.ReadAsync();
...
}
So in all the cases they use some method which is already async. And this is not what I need.
Let's say that I have a heavy method that does something:
public void DoSomthing()
{
...
}
And there is method where I call this DoSomething:
public void MajorMethod()
{
DoSomething();
}
I want to make DoSomething ayncthonous and call it.
The only solution I see would be the following one:
public Task MajorMethod()
{
return Task.Run(()=>DoSomething());
}
But I read some comments that it's not really the async. So how can I make DoSomething async?
If the MajorMethod has no other things to do other than calling the DoSomething, your code is fine.
But if you need to do other stuff after calling to DoSomething, then mark MajorMethod as async, and use await before Task.Run
public async Task MajorMethod()
{
await Task.Run(()=>DoSomething());
//stuff in here will executed after DoSomething completed
}
Examples from MSDN: Asynchronous programming
or just google c# async
You should be clear about the role async/await play in the Task Asynchronous Pattern. Making an async method does not parform an operation asynchronously just like that. Marking an existing method async will not magically perform everything in there asynchronously. Its main effect is that now you are allowed to use await within the method (I read that it even was discussed if the async keyword was necessary at all; it was added to avoid a breaking change when a local variable in existing methods would be named await).
await also does not provide asynchrony by itself, it provides a way to synchronize to another asnychronous method and yield while the other operation is still running. You can await another async method, but unless somwhere down the chain there is an actual Task running in another thread, the async method might even return synchronously.
In consequence this means that you need an operation that runs asynchronously first (such as a DB query, file access, network communication) and from there you create a chain of async methods that await the previous method.
Now in your case, when you have a computationally intensive method that does not wait for external resources, you can choose to perform the operation asynchronously. Since modern CPUs usually have more than one core at your disposal, you can increase both, performance and application responsiveness like that. The method would not be async, since it does not await anything:
void DoSomething()
{
//...
}
Task DoSomethingAsync() {
return Task.Run(DoSomething);
}
All callers of DoSomethingAsync can now use await to synchronize with this operation running in the background (note the change in return type to Task to allow callers to await):
async Task MajorMethod() {
//...
await DoSomethingAsync();
//...
}
This would allow callers of MajorMethod to synchronize with it. What you can also do is to do stuff in MajorMethod while DoSomethingAsync is running (and still await to allow callers to do even more parallel operations):
async Task MajorMethod() {
//This part will run before DoSomethingAsync
//...
Task doSomethingTask = DoSomethingAsync();
//This part is executed at the same time as DoSomethingAsync
//...
await doSomethingTask; //Here the caller can do more operations while DoSomething is running
//This part will be executed after DoSomethingAsync has finished
//...
}
This form of acquiring a task, doing something and only then awaiting the task has to be done somewhere in the chain, otherwise you have no benefit from the asynchronous operation. Even though this might be an overgeneralization, since synchronization can happen in more subtle ways, for example with a custom synchronization context. But as far as your question is concerned, you should go with: There is an actual task on one end and something that is done after the async call, but before the await on the other end.

Where to use Task.Run if using a library does not support async await

I have an application which sends a message over the network, and I would like to perform other work while waiting for the message to be sent and responded to. I start the messaging process by calling "await SendMessageAsync", which has the following duties:
public async Task<bool> SendMessageAsync()
{
//Do Some Work
//Send First Message
//More Work
//Send Second Message
//More Work
//Send Third Message
}
If my third party library supported it, I would write it like this:
public async Task<bool> SendMessageAsync()
{
//Do Some Work
await LibrarySendMessageAsync(firstMessage);
//More Work
await LibrarySendMessageAsync(secondMessage);
//More Work
await LibrarySendMessageAsync(thirdMessage);
}
However SendMessageAsync is not working properly with timeouts. So I'll need to introduce some parallelism and use Task.Run.
My question is: would it be better to wrap the entire above method in Task.Run, or to wrap each SendMessage method in its own Task.Run?
public async Task<bool> SendMessageAsync()
{
//Do Some Work
await Task.Run(() => LibrarySendMessage(firstMessage));
//More Work
await Task.Run(() => LibrarySendMessage(secondMessage));
//More Work
await Task.Run(() => LibrarySendMessage(thirdMessage));
}
VS
public async Task<bool> SendMessageAsync()
{
await Task.Run(() =>
{
//Do Some Work
LibrarySendMessage(firstMessage);
//More Work
LibrarySendMessage(secondMessage);
//More Work
LibrarySendMessage(thirdMessage);
});
}
Performance (speed) is very important for this application. SendMessageAsync will be called repeatedly in a high frequency.
It depends.
Wrapping the whole thing in a single Task.run is logically simpler to reason with. Once the task is created, the three messages are sent synchronously. synchronous code is always simpler to write, read, and debug
It is more complicated when it comes to performance. In both cases, the 3 messages are sent in an ordered sequence.
Three Task.Runs consume less thread(thread is returned faster to the pool) but will create more tasks as well as incur the cost of transitioning from one task to another. A single task will cause the thread to block longer then necessary. You will need more threads in the thread pool to handle the same amount of messages. You will be balancing the cost of waking up the thread to continue execution and picking a task from the queue to continue execution.
The balance will depend on how long does sending the 3 messages take, how many thread pool thread you can afford to have, what will the expected through put be, and even the pattern of the message arrival(evenly vs sporadic). And, of course, eventually everything depends on profiling.
Basically your second option... you have a method :-
public async Task<bool> SendMessageAsync()
which basically shouldn't be async. You are saying basically you want the method to be synchronous.... so write that method
public bool SendMessage()
{
//Do Some Work
LibrarySendMessage(firstMessage);
//More Work
LibrarySendMessage(secondMessage);
//More Work
LibrarySendMessage(thirdMessage);
}
Don't write synchronous code as weird confused async method. So then if you you want to do that work in a thread then await...
await Task.Run(() => SendMessage());
which you can wrap into your original method SendMessageAsync

AsyncAwait Concept

I'm trying to understand the concept of async and await and can't quite grasp the concept of it. Up to what I've learned is in Async-await if we call a method-A and then call method-B using await from method-A then the reminder of method-A will run only after method-B's work is completed. Am I missing something? Please correct me.
If that is the case then every time we call a method even with using synchronous programming, the reminder of the method-A waits until we have finished calling method-B?
public void methodA(){
methodB();
Console.Writeline("MethodB has been called");
}
public void methodB(){//do stuff}
Now with async await:
public async Task methodA(){
await methodB();
Console.Writeline("MethodB has been called");
}
public async Task methodB(){//do stuff}
Please mind me showing the difference? I'm having really hard time trying to grasp the concept. Generally, I see posts on ThreadPool and Threads, but without having a clear concept, I don't quite get it.
async and await are about getting threads to do useful work rather than sitting idly waiting for other work to complete.
If we write code that creates a new thread to do some work, and then immediately block our current thread to wait for that to finish, that's a waste. Why would we not just run the code on our current thread and have it complete useful work, and save ourselves the overhead of creating a new thread?1
So, what does await do? It allows our current method to return to its caller sooner than when all of its work is complete. That is, we're indicating that we've got no current use for the thread that we're running on, but hopefully our caller, or our callers caller, etc, does have something else it can be usefully running on our thread.
What if our method has something else it can usefully do on the current thread? Easy - decouple the creation of an awaitable from the await itself, and do that other useful work between:
public async Task methodA(){
var mba = methodB();
Console.Writeline("MethodB has been called");
//Other useful work that doesn't depend on methodB
var result = await mba
//And now continue with the result from methodB
}
How methodB itself achieves its asynchrony is entirely an implementation detail of methodB - all we know is that it's arranged to complete its returned Task at some future point in time (this is why other languages use terms such as "futures" or "promises" where we use "task")
1For those wondering why this paragraph exists, it's to exactly rebut the all too common claim that await "creates a new thread" or similar.
Up to what I've learned is in Async-await if we call a method-A and then call method-B using await from method-A then the reminder of method-A will run only after method-B's work is completed.
You are kind of right.
Let's take a look at a practical situation where async await would be used.
Let's say you have a Windows Forms program. On the form, there is a button. When the user presses this button, the program will fetch some stuff from the internet. After the response is received, it displays the response in a label.
Obviously, requesting stuff on the internet takes a rather long time, compared to other operations like adding stuff together, drawing a text box etc.
If you don't use async-await, the form will not respond to user interactions while the program is waiting for the response from the server. That's bad UX.
Now let's use async-await. I will use the code that you have provided:
public async Task methodA(){
await methodB();
Console.Writeline("MethodB has been called");
}
public async Task methodB(){//do stuff}
methodA is called when the button is pressed. methodB fetches the data. When the await line is reached, methodA returns immediately just after methodB is called. This way, the program execution does not need to stay in methodA so the form can respond to user interactions. A state machine is created to remember where the execution was in methodA. After methodB returns, execution goes back to methodA and execute the rest of it.

Categories