2024-08-31 15:35:12 +08:00
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Threading.Tasks ;
2024-10-17 01:59:25 +08:00
namespace JNGame.Runtime.Util
2024-08-31 15:35:12 +08:00
{
/// Author: Pim de Witte (pimdewitte.com) and contributors, https://github.com/PimDeWitte/UnityMainThreadDispatcher
/// <summary>
/// A thread-safe class which holds a queue with actions to execute on the next Update() method. It can be used to make calls to the main thread for
/// things such as UI Manipulation in Unity. It was developed for use in combination with the Firebase Unity plugin, which uses separate threads for event handling
/// </summary>
public class UnityMainThreadDispatcher : SingletonScene < UnityMainThreadDispatcher > {
private readonly Queue < Action > _executionQueue = new Queue < Action > ( ) ;
public void Update ( ) {
lock ( _executionQueue ) {
while ( _executionQueue . Count > 0 ) {
_executionQueue . Dequeue ( ) . Invoke ( ) ;
}
}
}
/// <summary>
/// Locks the queue and adds the IEnumerator to the queue
/// </summary>
/// <param name="action">IEnumerator function that will be executed from the main thread.</param>
public void Enqueue ( IEnumerator action ) {
lock ( _executionQueue ) {
_executionQueue . Enqueue ( ( ) = > {
StartCoroutine ( action ) ;
} ) ;
}
}
/// <summary>
/// Locks the queue and adds the Action to the queue
/// </summary>
/// <param name="action">function that will be executed from the main thread.</param>
public void Enqueue ( Action action )
{
Enqueue ( ActionWrapper ( action ) ) ;
}
/// <summary>
/// Locks the queue and adds the Action to the queue, returning a Task which is completed when the action completes
/// </summary>
/// <param name="action">function that will be executed from the main thread.</param>
/// <returns>A Task that can be awaited until the action completes</returns>
public Task EnqueueAsync ( Action action )
{
var tcs = new TaskCompletionSource < bool > ( ) ;
void WrappedAction ( ) {
try
{
action ( ) ;
tcs . TrySetResult ( true ) ;
} catch ( Exception ex )
{
tcs . TrySetException ( ex ) ;
}
}
Enqueue ( ActionWrapper ( WrappedAction ) ) ;
return tcs . Task ;
}
IEnumerator ActionWrapper ( Action a )
{
a ( ) ;
yield return null ;
}
}
}