[c#] Wait for a void async method

How can I wait for a void async method to finish its job?

for example, I have a function like below:

async void LoadBlahBlah()
{
    await blah();
    ...
}

now I want to make sure that everything has been loaded before continuing somewhere else.

This question is related to c# asynchronous

The answer is


Best practice is to mark function async void only if it is fire and forget method, if you want to await on, you should mark it as async Task.

In case if you still want to await, then wrap it like so await Task.Run(() => blah())


do a AutoResetEvent, call the function then wait on AutoResetEvent and then set it inside async void when you know it is done.

You can also wait on a Task that returns from your void async


If you can change the signature of your function to async Task then you can use the code presented here


You don't really need to do anything manually, await keyword pauses the function execution until blah() returns.

private async void SomeFunction()
{
     var x = await LoadBlahBlah(); <- Function is not paused
     //rest of the code get's executed even if LoadBlahBlah() is still executing
}

private async Task<T> LoadBlahBlah()
{
     await DoStuff();  <- function is paused
     await DoMoreStuff();
}

T is type of object blah() returns

You can't really await a void function so LoadBlahBlah() cannot be void


The best solution is to use async Task. You should avoid async void for several reasons, one of which is composability.

If the method cannot be made to return Task (e.g., it's an event handler), then you can use SemaphoreSlim to have the method signal when it is about to exit. Consider doing this in a finally block.


I know this is an old question, but this is still a problem I keep walking into, and yet there is still no clear solution to do this correctly when using async/await in an async void signature method.

However, I noticed that .Wait() is working properly inside the void method.

and since async void and void have the same signature, you might need to do the following.

void LoadBlahBlah()
{
    blah().Wait(); //this blocks
}

Confusingly enough async/await does not block on the next code.

async void LoadBlahBlah()
{
    await blah(); //this does not block
}

When you decompile your code, my guess is that async void creates an internal Task (just like async Task), but since the signature does not support to return that internal Tasks

this means that internally the async void method will still be able to "await" internally async methods. but externally unable to know when the internal Task is complete.

So my conclusion is that async void is working as intended, and if you need feedback from the internal Task, then you need to use the async Task signature instead.

hopefully my rambling makes sense to anybody also looking for answers.

Edit: I made some example code and decompiled it to see what is actually going on.

static async void Test()
{
    await Task.Delay(5000);
}

static async Task TestAsync()
{
    await Task.Delay(5000);
}

Turns into (edit: I know that the body code is not here but in the statemachines, but the statemachines was basically identical, so I didn't bother adding them)

private static void Test()
{
    <Test>d__1 stateMachine = new <Test>d__1();
    stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
    <TestAsync>d__2 stateMachine = new <TestAsync>d__2();
    stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
    return stateMachine.<>t__builder.Task;
}

neither AsyncVoidMethodBuilder or AsyncTaskMethodBuilder actually have any code in the Start method that would hint of them to block, and would always run asynchronously after they are started.

meaning without the returning Task, there would be no way to check if it is complete.

as expected, it only starts the Task running async, and then it continues in the code. and the async Task, first it starts the Task, and then it returns it.

so I guess my answer would be to never use async void, if you need to know when the task is done, that is what async Task is for.