Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Why are we going with async void for the built in functions?

Discussion in 'Experimental Scripting Previews' started by leftler, Oct 24, 2017.

  1. leftler

    leftler

    Joined:
    Feb 4, 2016
    Posts:
    9
    I was starting to look in to using async/await and came across the article https://blogs.msdn.microsoft.com/appconsult/2017/09/01/unity-coroutine-tap-en-us/, I was very surprised to see that if we wanted to await a task in a MonoBehavior message that accepts either a void or an IEnumerator return type we must return async void as a return type or just normal void and never await the async function's returned value.

    Is the article incorrect (I tried to find the documentation about async/await in the unity online manual but could not find it)? If it is not incorrect and we do have to use async void I think this should be changed. This pattern violates the standard pattern the rest of the .NET ecosystem has cultivated. For example when doing MVC 6 your controller methods can return void or can return task depending on if they are async. Same for Unit tests using almost every unit test software out there.

    In fact you already do this pattern with IEnumerator. I propose any MonoBehavior message that can return void or IEnumerator should also allow you to return Task. Even if all you do under the hood is ignore the return value, it still makes user code follow standard coding patterns and does not teach people new to C# to violate the one rule we pound in to them all the time on StackOverflow questions on async/await (Never do async void unless you are writing a event handler because you can't change its signature).
     
  2. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    It makes sense that it's async void. As the resultant function signature matches that of original set of void-based engine callbacks.

    "Async void should be used in fire-and-forget situations where the caller does not need to await the result of the computation.", which perfectly fits the engine callbacks used by Unity. The engine is calling into Update, but doesn't use the returned results of Update. In using async void, it will continue to operate normally without holding up the main thread, while awaiting any asynchronous call within the callback body.

    The following code is perfectly valid, and DoSomethingElse will only execute after awaiting the results of DoSomethingAsync.
    Code (CSharp):
    1. async void Awake() {
    2.   await DoSomethingAsync();
    3.   DoSomethingElse();
    4. }
    The only thing this hampers is calling said callbacks in other user-code, which, in my opinion, shouldn't be done at all.
     
    MurphyMurph_21 likes this.
  3. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    96
    The problem with async void though is with exceptions generally, since they get lost in that case and you get mysterious crashes that don't have any visible exceptions.

    You want to avoid async void generally, in favor of async task. More info here: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx