Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested Async Await Does not Wait

I think I missunderstanding the behaviour of async await in c#.

I have two methods that return a Task defined like

public async Task Name()
{
await AsyncOperation() 
}

Imagine AsyncOperation() like an PostAsync of HttpClient.

Now I call them inside some other methods

public asyn Task Method()
{
await Name1(() => { "bla bla"});
await Name2();
Console.WriteLine("Continue");
}

This works as expected to me. Waits until Name1() and Name2() finish and then continues.

Now I need to nest Name1() and Name2(). In fact Name1() is a Please Wait Window that recieve as lambda parameters a slow operation, while Name2() is a slow download of a file. I want the Plese Wait window appears while the file is downloaded.

So I try something like this:

public asyn Task Method()
{
    await Name1( async ()=>
    {
        await Name2();
    }
    Console.WriteLine("Continue");
}

In this case the execution doesnt wait untile Name2() finished. Why this happen and await doesnt wait?

Update

This is the logic behind the method of please wait. It shows a Please Wait message using Mahapps Dialogs, executes the code that recieves by the lambda, and then close the please wait message.

public static async Task Name1(Action longOperation)
{
    _progressController = await _metroWindow.ShowProgressAsync("Please wait...");            
    await Task.Run(() => longOperation());
    await _progressController.CloseAsync();
}
like image 563
Ricardo Polo Jaramillo Avatar asked Jul 13 '14 01:07

Ricardo Polo Jaramillo


People also ask

Does async-await wait?

The await operator is used to wait for a Promise and get its fulfillment value. It can only be used inside an async function or a JavaScript module.

What happens when async method is not awaited?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.

Can async void be awaited?

For methods other than event handlers that don't return a value, you should return a Task instead, because an async method that returns void can't be awaited. Any caller of such a method must continue to completion without waiting for the called async method to finish.

Does await blocks the next line?

await only blocks the code execution within the async function. It only makes sure that the next line is executed when the promise resolves. So, if an asynchronous activity has already started, await will not have an effect on it.


1 Answers

The Name1 method takes a delegate and returns a Task<T> where T is the type returned by the delegate. In your case, the delegate returns Task, so we get Task<Task> as the result. Using await waits only for the completion of the outer task (which immediately returns the inner task) and the inner task is then ignored.

You can fix this by dropping the async and await in the lambda function.

Also, take a look at Asynchronous Gotchas in C#.

like image 148
djikay Avatar answered Nov 02 '22 14:11

djikay