Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Async methods do not stop executing when exiting play mode. Intended?

Discussion in 'Scripting' started by Prodigga, Aug 9, 2018.

  1. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    785
    Hi, pretty much just the title. All static variables become null, coroutines stop, but async methods continue executing. Is this intended?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,741
    I wouldn't say intended necessarily.

    But yes, threads you've spun up yourself don't necessarily stop when exiting play mode in the editor. Since exiting play mode doesn't stop the program, it just exits execution of scripts and resets the scene.

    But then again, static variables shouldn't become null. That is unless they are unity objects, in which case they're destroyed and they'll equate to null due to the == operator overload the unity uses.
     
  3. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    785
    Yeah, the 'static variables shouldn't become null' part is why I thought this was a bit strange.

    The only workaround I can think of seems to be to add if(Application.IsPlaying) checks after every await which really doesn't seem like the way I should be handling this issue. :)

    Imagine having to micromanage static variables if they didn't reset.

    I think the 'expectation' is that we have a 'clean slate' every time we hit play/stop.
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,389
    Well, it is in line with how programs generally work. A program is running as long as it has at least one active thread. So outside the editor it should behave the same. Stopping the main thread generally doesn't automatically stop all the other threads, which is intended.
     
  5. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    785
    Edit: I'm under the impression here that stopping the game also resets the state of static variables "somehow", while Async methods continue executing. I'll have to test tomorrow but maybe the static variables don't get reset until you re-play? Does re-playing trigger an assembly reload which is what actually causes static variables to reset to their default values? That'd mean it would kill any lingering async tasks, too. Will have to test tomorrow.

    And again, by that logic, static variables shouldn't reset either. But they do. And of course they do, right? Clearly the intention here by Unity was for a "clean slate" when you hit the stop button. Otherwise it would be a mess. I understand *why* the asynchronous methods continue executing. The question is whether they *should* continue.

    It makes writing async game logic really painful. You need to perform checks after each await call to ensure the application is still playing. And these checks needs to be in our runtime scripts only because of this editor "quirk". For code that executes in a build, this is never an issue, since there is no "pause and replay" button. So we end up having to write code that needs to have termination points after every await statement *just incase* we are executing in the editor, when it won't even be an issue in a real build of the game.

    Not to mention other quirks, like consider the following code:

    Code (CSharp):
    1. async void Test()
    2. {
    3.     string result = await LongRunningTask();//completes in 10 seconds
    4.     gameobject.name = result;
    5. }
    Imagine this. You invoke Test. And before LongRunningTask completes, you stop and start the game. Because Async methods don't get cancelled, LongRunningTask eventually completes, and attempts to set the name of the GameObject to result. There is code being executed from the *previous* play session in the *new play session*.

    Not to mention that you wouldn't even be able to work around the issue in this example with a simple ''if(Application.isPlaying)" above line 4 because the application *is* playing. It's not the same 'play session' as the one that invoked the asynchronous method, though.
     
    Last edited: Aug 9, 2018
  6. Brice-xCIT

    Brice-xCIT

    Joined:
    Jun 22, 2017
    Posts:
    5
    Thanks for this thread. I just encountered this in Unity 2018.2.2f1.

    It feels very much like a bug to me, especially since async methods in fact run in the player's Main Thread, and Unity's SynchronizationContext should really be able to terminate the tasks since, in my understanding, it is already able to collect them to force them to run into the main thread.
     
    paulomuggler likes this.