Kirzy
Kirzy

Reputation: 148

Convert void into async return in C#

I read that returning void from a C# async call is not good. But I have the following scenario:

public async void MainFunction()
{
    await DoSomething()
    await DoSomethingMore()
}

public void DoSomething() 
{
    //some code that I want to execute (fire and forget)
}

public void DoSomethingMore()
{
    //some code that I want to execute (fire and forget)
}

Since I just want that function be executed with no return at all. Should i keep it like this, or should I return Task from DoSomething()? If I change it to return Task, since my code doesn't need to return anything at all, what should I return?

Upvotes: 6

Views: 9310

Answers (2)

Simple Fellow
Simple Fellow

Reputation: 4622

you can return either of these

Task.FromCompleted;
Task.FromException(ex);

so your method would be like this:

public void MainFunction()
{
    await DoSomething()
    await DoSomethingMore()
}

public Task DoSomething() 
{
    try{

     //some code that I want to execute (fire and forget)

     return Task.FromCompleted;
   }
   catch(Exception ex){
     return Task.FromException(ex);
   }

}


    //some code that I want to execute (fire and forget)
}

public Task DoSomethingMore()
{
       try{

     //some code that I want to execute (fire and forget)

     return Task.FromCompleted;
   }
   catch(Exception ex){
     return Task.FromException(ex);
   }
}

Upvotes: 6

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149548

If i change it to return Task, since my code need return nothing at all, what should i return?

Your current code wouldn't compile, as you can't await on a void returning method (because it doesn't return an awaitable, which is a type which exposes a GetAwaiter method).

Any void method in the synchronous world should return a Task in the asynchronous world. This allows for anyone who wishes to asynchronously wait on the async operation, and also gets a chance to handle exceptions properly. using async void means that the exception will either be swallowed, or if set to in the configuration, will be rethrown on an arbitrary threadpool thread. Async should be propagated properly all the way.

Note that when you await both operations in MainFunctionAsync, you're not firing and forgetting, you're asynchronously waiting for each of them to complete, sequentially.

public async Task MainFunctionAsync()
{
    await DoSomethingAsync();
    await DoSomethingMoreAsync();
}

public Task DoSomethingAsync() 
{
    // Do meaningful async stuff
}

public Task DoSomethingMoreAsync()
{
    // Do more meaningful async stuff
}

Upvotes: 10

Related Questions