We are using an external library that lets us await a longer task via the async/await pattern. We need to await this job while an animation is running at the same time. If we just await the task naively, the animation gets stuck until the task has been finished.
We did not get an error for this and expected the Coroutine to await the Task. But this is not the case. Instead, it seems to just wait for the next frame (like with yield return null; ) and then continues with ProcessingTheResultsOfTheTask(), which in our case causes a race condition, because the results of the task are not available yet.
This works fine. But the library is from 2017 and does not appear to be actively maintained. The latest issue is over one year old, without any response. And this issue also includes a hint that the library is not really working reliably. Introducing such a library always bears the risk of causing problems with future Unity releases.
So I am wondering if thereās a better (built-in) way to actually await a Task inside a Coroutine as of 2020?
As a side-note: Wrapping the async function in yet another async void function did not work either, because async void functions donāt cause the caller to wait, and hence weāre running into the race condition again.
Thanks waldgeist! I just had this same problem of taking an existing Coroutine and meshing it with an asynchronous Task and your code worked perfectly!
How did you get this to work? For me doing yield return new WaitUntil(()=> task.isCompleted) simply hangs the entire app and doesnāt continue to the next frame until the task is done?
IEnumerator RefreshLobbyCoroutine()
{
var delay = new WaitForSecondsRealtime(2);
while (lobby != null)
{
// Run task and wait for it to complete
var t = Task.Run(async () => await Lobbies.Instance.GetLobbyAsync(lobby.Id));
yield return new WaitUntil(() => t.IsCompleted);
// Task is complete, get the result
lobby = t.Result;
yield return delay;
}
}
I just wanted to say that, after searching for this a while, I found the a 3rd party solution that Unity veterans probably all know about already.
This is probably what most people are looking for when it comes to a general solution for integrating async/await with coroutines in most cases.
I havenāt used this in a professional project yet, so take with a grain of salt, but it seems like itās at least somewhat maintained, and claims to work across release platforms (though, if I were you, Iād confirm on all your targets before investing in this library, donāt just take this randoās uninformed opinion on it).
Sorry for the necro, but can someone please explain the difference between
Task t = FunctionReturningTheAsyncTask();
and Task t = Task.Run(async () => await FunctionReturningTheAsyncTask());
both followed by yield return new WaitUntil(() => t.IsCompleted);
Edit; Unity 2021.3.2f1
both of which have been suggested in this thread. Why can I call Unity API functions in the task created in the former fashion, but I get exceptions regarding the main/update thread when using the latter? I donāt understand the nuts and bolts of the difference between those invocations, and hoping someone can clarify.
Task.Run creates a new thread (kinda but no need to know all the details) to run that block of code. Unity API can only be called from the main thread to avoid freezing or crashing the app. You can check what thread number you are on with Thread.CurrentThread, main thread should be ā1ā if I remember correctly.
Meanwhile, the first method is just wrapping the Task capabilities and running on the main thread.
Both methods check for the task completion on the main thread so thereās no problem there.