Last active
July 27, 2022 16:45
-
-
Save starikcetin/7f7d922d92672570abd71ef3adf60668 to your computer and use it in GitHub Desktop.
Main thread dispatcher for Unity.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
// TODO: Make sure Singleton implementation is also thread-safe. | |
/// <summary> | |
/// Provides means of executing code on the main Unity thread while in other threads. | |
/// </summary> | |
public class MainThreadDispatcher | |
{ | |
private readonly SynchronizationContext _syncContext = SynchronizationContext.Current; | |
/// <summary> | |
/// Dispatches an action to the Unity main thread, and waits for either an answer or action completion. | |
/// </summary> | |
/// <remarks> | |
/// This code, when run in a background thread: | |
/// <code> | |
/// Debug.Log("Before"); | |
/// MainThreadDispatcher.Instance.DispatchAndWait(() => Debug.Log("Inside")); | |
/// Debug.Log("After"); | |
/// </code> | |
/// Produces the following console output: | |
/// <code> | |
/// Before | |
/// Inside | |
/// After | |
/// </code> | |
/// Notice 'After' appearing after 'Inside'. | |
/// </remarks> | |
/// <seealso cref="DispatchFireAndForget"/> | |
public void DispatchAndWait(Action action) | |
{ | |
_syncContext.Send(_ => action?.Invoke(), null); | |
} | |
/// <summary> | |
/// Dispatches an action to the Unity main thread but doesn't wait for an answer or action completion. | |
/// </summary> | |
/// <remarks> | |
/// This code, when run in a background thread: | |
/// <code> | |
/// Debug.Log("Before"); | |
/// MainThreadDispatcher.Instance.DispatchFireAndForget(() => Debug.Log("Inside")); | |
/// Debug.Log("After"); | |
/// </code> | |
/// Produces the following console output: | |
/// <code> | |
/// Before | |
/// After | |
/// Inside | |
/// </code> | |
/// Notice 'After' appearing before 'Inside'. | |
/// </remarks> | |
/// <seealso cref="DispatchAndWait"/> | |
public void DispatchFireAndForget(Action action) | |
{ | |
_syncContext.Post(_ => action?.Invoke(), null); | |
} | |
// | |
// Alternative implementation below with a ConcurrentQueue: | |
// | |
// private readonly ConcurrentQueue<Action> _queue = new ConcurrentQueue<Action>(); | |
// | |
// public void Dispatch(Action action) | |
// { | |
// _queue.Enqueue(action); | |
// } | |
// | |
// private void Update() | |
// { | |
// if (_queue.IsEmpty) | |
// { | |
// return; | |
// } | |
// | |
// while (_queue.TryDequeue(out var action)) | |
// { | |
// action?.Invoke(); | |
// } | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment