using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace Unity.XR.XREAL
{
///
/// A singleton MonoBehaviour class that dispatches actions to be executed on the Unity main thread.
///
public class XREALMainThreadDispather : SingletonMonoBehaviour
{
ConcurrentQueue m_Actions = new ConcurrentQueue();
ConcurrentQueue m_RunningActions = new ConcurrentQueue();
///
/// Event invoked every frame during the Update method.
///
public static event Action OnUpdate;
///
/// Queues an action to be executed on the Unity main thread in the next frame.
///
/// The action to execute on the main thread.
public void QueueOnMainThread(Action action)
{
m_Actions.Enqueue(action);
}
///
/// Queues an action to be executed on the Unity main thread after a specified delay.
/// Returns a CancellationTokenSource that can be used to cancel the scheduled action.
///
/// The action to execute on the main thread.
/// The delay in seconds before the action is executed.
/// A CancellationTokenSource that can be used to cancel the scheduled action.
public CancellationTokenSource QueueOnMainThreadWithDelay(Action action, float delaySeconds)
{
CancellationTokenSource ctSource = new CancellationTokenSource();
Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(delaySeconds));
if (!ctSource.IsCancellationRequested)
m_Actions.Enqueue(action);
}, ctSource.Token);
return ctSource;
}
void Update()
{
OnUpdate?.Invoke();
if (m_Actions.Count > 0)
{
(m_Actions, m_RunningActions) = (m_RunningActions, m_Actions);
while (m_RunningActions.TryDequeue(out var action))
{
try
{
action.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
}
}
#if UNITY_ANDROID && !UNITY_EDITOR
void OnApplicationPause(bool pause)
{
Debug.Log($"[XREALMainThreadDispather] OnApplicationPause: {pause}");
if (pause)
{
XREALPlugin.PauseSession();
}
else
{
XREALPlugin.ResumeSession();
}
}
#endif
}
}