3
public void DoStuff()
{
    // I want to be able to call the method DoAsynckStuff and wait for the result.
    // I know that's not a usual thing to do
    // Usually also this will be async method and then just await the result.
    // I need this to be something like 
    var resultTask = DoAsynckStuff();
    resultTask.Wait();
    var result = resultTask.Result;
    //.....
}

public async Task<string> DoAsynckStuff()
{
    //...
}

Sorry, I'm new to async-await. What I need is that I want to wait for the result of a specific async method. I can't make the method async because it will cause some problems with the methods that will call that one.

I have tried the Wait method on the Task, just like on the code sample. But the task status will be always "waiting for activation".
I also tried to call the method resultTask.Start() before the wait method but that will throw

System.InvalidOperationException: Start may not be called on a promise-style task.

also result.RunSynchronously() will throw that exception.

I also viewed this article and some others but couldn't get into a result

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Game dev
  • 296
  • 2
  • 17
  • What is the type of the application? WinForms maybe? Also how do you know that the status of the task is `WaitingForActivation`? Are you running the code with the debugger of the Visual Studio? – Theodor Zoulias Oct 16 '22 at 22:44
  • It is a Unity application. Yeah, I'm using the visual studio debugger. – Game dev Oct 16 '22 at 22:48
  • 1
    Take a look at this question: [An async/await example that causes a deadlock](https://stackoverflow.com/questions/15021304/an-async-await-example-that-causes-a-deadlock). It explains the cause of the problem, and shows how to solve it. – Theodor Zoulias Oct 16 '22 at 23:08
  • 1
    If you have awaitable async stuff, you should await it within an `async` method (that returns a Task). Callers should follow the same rules. Once you work yourself up the stack and get to an event handler (that only gets called by some sort of framework), make that handler `async void`. Read up on this in @stephencleary's blog (https://blog.stephencleary.com/), particularly the parts about how easy it is to deadlock yourself by blocking/waiting on a task's result – Flydog57 Oct 16 '22 at 23:14
  • Thanks for the blogs, I will definitely check them out. – Game dev Oct 16 '22 at 23:24

2 Answers2

2

Try doing something like this:

void Main()
{
    var resultTask = Task.Run(() =>  DoAsyncStuff().Result );
    resultTask.Wait();
    
    Console.WriteLine(resultTask);
}

// You can define other methods, fields, classes and namespaces here

public async Task<string> DoAsyncStuff()
{
    string output = "Task Complete";
    Thread.Sleep(2000);
    return output;
}

this outputs:

Task Complete

enter image description here

mathis1337
  • 1,426
  • 8
  • 13
  • 1
    This should achieve what you are wanting. – TravTanker Oct 16 '22 at 22:53
  • Okay I'm going to try that Right now – Game dev Oct 16 '22 at 22:56
  • The .Wait() can be optional, but in the event a race condition as I am not sure how you are using the method it might be safer to have. – mathis1337 Oct 16 '22 at 22:56
  • Actually after calling the wait the response was an exception, Values below `Id = 1, Status = RanToCompletion, Method = {null}, Result = Exception of type 'System.Reflection.TargetInvocationException' was thrown` – Game dev Oct 16 '22 at 23:13
  • Like I said it was optional. Since you didn't actually post the code and in my example it is valuable because the method has an awaiting event, but glad you solved it. – mathis1337 Oct 16 '22 at 23:24
  • ` var result = Task.Run(() => TimingApiService.GetMonthlyCalendar(targetDay)); // result.Wait(); UpdateTimings?.Invoke(result.Result, SaveSystem.LoadCity());` Here is the call I'm using, Without wait it throws: ```Id = 1, Status = RanToCompletion, Method = {null}, Result = Exception of type 'System.Reflection.TargetInvocationException' was thrown``` But thank you, now it's solved – Game dev Oct 16 '22 at 23:29
1

It sounds like you're running your application with a synchronization context, like WinForms or WPF.

Anyway, the correct approach to run asynchronous code synchronously is to start a new thread and wait on it.

var result = Task.Run(() => DoAsyncStuff()).Result;
José Ramírez
  • 872
  • 5
  • 7
  • I'm sorry the DoAsyncStuff is an async method, sorry just edited the post. I have tried that but that doesn't take me anywhere. The status of the Task will still always be `waiting for activation `. And it's a unity project. – Game dev Oct 16 '22 at 22:51
  • My code is not saving a task anywhere. `result` is what you want, it is what you need in the end. My one line repaces 3 of your lines. – José Ramírez Oct 16 '22 at 22:55
  • Yeah, that worked, sorry before I was using `...()=>await DoAsyncStuff() `. Thank you :). – Game dev Oct 16 '22 at 23:19