Skip to content

Cannot use for Editor unit testing, as SyncContextUtil.Install is not called except at runtime #9

Description

@jokigenki

I hacked this by making SyncContextUtil.Install public and calling it in my tests SetUp method, but I don't know if there's a better way?

Activity

  1. svermeulen commented on Sep 7, 2018

    @svermeulen
    Contributor

    We should probably change it to use the [InitializeOnLoad] instead of [RuntimeInitializeOnLoad]. But I'd have to test it to be sure that works correctly

  2. svermeulen commented on Sep 7, 2018

    @svermeulen
    Contributor

    Since I'm not sure that runs before awake. But we could use both attributes in that case too

  3. StephenHodgson commented on Sep 7, 2018

    @StephenHodgson

    Unity also doesn't support executing the async in the editor as well, you'll also need a pump.

    See https://forum.unity.com/threads/async-await-in-editor-script.481276/

  4. StephenHodgson commented on Sep 7, 2018

    @StephenHodgson

    Here's an modified version of @svermeulen's project that I included in another project. I've been meaning to open pull requests to add this stuff back but I've been pretty busy.

    #if UNITY_EDITOR
            private static System.Reflection.MethodInfo executionMethod;
    
            /// <summary>
            /// HACK: makes Unity Editor execute continuations in edit mode.
            /// </summary>
            private static void ExecuteContinuations()
            {
                if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
                {
                    return;
                }
    
                var context = SynchronizationContext.Current;
    
                if (executionMethod == null)
                {
                    executionMethod = context.GetType().GetMethod("Exec", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                }
    
                executionMethod?.Invoke(context, null);
            }
    
            [UnityEditor.InitializeOnLoadMethod]
    #endif
            [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
            private static void Initialize()
            {
    #if UNITY_EDITOR
                UnityEditor.EditorApplication.update += ExecuteContinuations;
    #endif
                UnitySynchronizationContext = SynchronizationContext.Current;
                UnityThreadId = Thread.CurrentThread.ManagedThreadId;
            }
    
  5. anticrisis commented on Sep 21, 2018

    @anticrisis

    @StephenHodgson Thank you for this -- I was unable to find documentation of this after quite a bit of searching Unity's forums. Never occurred to me to just build my project and see that my async worked, and of course it did. The code you shared makes the editor work, too.

    Can this technique also be used to use the thread pool to run non-UI async tasks that don't need to access the Unity API?

    Does anyone know if there is official Unity documentation on this anywhere?

  6. jokigenki commented on Sep 22, 2018

    @jokigenki
    Author
  7. svermeulen commented on Sep 22, 2018

    @svermeulen
    Contributor

    @jokigenki You should be able to use the unity api with the async approach provided here. Assuming you don't use the multithreading awaiters then it should all remain on the same thread. It should be able to be used in a very similar way to coroutines except a much cleaner syntax and some more features

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions