0

i need to wait for my async void to finish. It has some await Task.Delay functions in it and I need them to finish before it continues. This void doesn't return anything so I don't see a reason to make it async Task<> and I also shuffle an array inside this void and I declare some variables. So how can I do this ? Is async Task<> the only way ? My void is not expecting any parameters/inputs.

svick
  • 236,525
  • 50
  • 385
  • 514

3 Answers3

8

Return Task (not Task<T>) instead of void. Note, the non-generic form of Task does not need to wrap a value. It's just for signalling completion or errors, not results. In the case of async methods, this is equivalent to a synchronous void return type. It means you can wait for your method to complete.

spender
  • 117,338
  • 33
  • 229
  • 351
  • Thanks for the quick response, after I change it to async Task how do i make the program wait for the "Task" to finish ? – QuestionsEverywhere Dec 18 '15 at 18:16
  • 1
    @QuestionsEverywhere the method that called it does `await YourMethod()`, you will then need to make that method Return a `Task` or `Task` too, then it's parent, then it's parent, all the way up. If you are going to use async/await you have to use it all the way up the call stack, you can't use it only at the bottom. – Scott Chamberlain Dec 18 '15 at 18:17
  • @QuestionsEverywhere you can store it in a variable. `var theTask = TheMethod();` and then you can wait for it when ever you need. `await theTask;` – M.kazem Akhgary Dec 18 '15 at 18:19
  • This "async all the way up the call stack" is a confusing thing in (for instance) a console app. At some point, you need to go synchronous. If you're in a console app, just `myNonGenericTask.Wait()` will block until the task completes, but don't be thinking that's a good idea in [a webapp](http://stackoverflow.com/questions/14526377/why-does-this-async-action-hang) or UI app. – spender Dec 18 '15 at 18:20
  • So i just switch the Void that is calling the async task to Task ? Shouldn't i use something like Task.WaitAll(FromVoidToTask()); – QuestionsEverywhere Dec 18 '15 at 18:20
  • 1
    @QuestionsEverywhere, no you switch `void` to `Task` not `Task`. And if you do `Task.WaitAll` you are going to likely cause a deadlock in your program. You need to change `void Foo() { YourOldVoidTask(); } async void YourOldVoidTask() { ... }` to `async Task Foo() { await YourOldVoidTask(); } async Task YourOldVoidTask() { ... }` You will also need to change whoever called `Foo()` to be async too, and whoever called that method to be async, all the way up till you get to a event or some public API you are exposing or `Main()`. `Main()` is the only place you are allowed to do `.Wait()`. – Scott Chamberlain Dec 18 '15 at 18:22
  • 1
    Go read the article I linked to in your question, specifically the "Async all the way" section. – Scott Chamberlain Dec 18 '15 at 18:24
  • Great ! This answer was much more clearer than your previous one ^^ – QuestionsEverywhere Dec 18 '15 at 18:24
  • Another option is to wait like that: `theTask.GetAwaiter().GetResult()` – madoxdev Jun 20 '19 at 13:33
1

Every async function should return Task instead of void and Task<TResult> instead of TResult. The only exception of this is the event handler.

So if your async function isn't an event handler it should return Task. Once this is done you can await for it...

... ehm, provided that your function is also declared async and returns Task or Task<TResult>, which makes that your clients all must be async.

If you have a sync function and want to call an async function use the following:

var myTask = Task.Run( () => SomeAsyncFunction(...));
// while my task is running you can do other things
// after a while you need the result:
Task.Wait();

// only if SomeAsyncFunction returns Task<TResult>:
TResult result = Task.Result();

Be aware though that this will halt your function until the task is finished. So when possible consider making your function also async. The code would be like:

public async void Button1_Clicked(object Sender, ...)
{
    var task = MySlowMultiplier(3, 4);
    // while task running you can do other things
    // the UI remains responsive
    // after a while:
    int result = await task;
    ProcessResult(result);
 }

 private async Task<int> MySlowMultiplier(int x, int y)
 {
     // I'm really slow:
     await Task.Delay(TimeSpan.FromSeconds(5));
     return x * y;
 }
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
-1

You can use this code.

var result = Task.Run(async() => { return await METHODNAMEHERE(); }).Result;
Trung
  • 1,819
  • 1
  • 13
  • 10