Skip to content

Instantly share code, notes, and snippets.

@afterburn
Created April 25, 2023 21:52
Show Gist options
  • Save afterburn/9c1bfa8a0376b28fed9ddf1e878bf214 to your computer and use it in GitHub Desktop.
Save afterburn/9c1bfa8a0376b28fed9ddf1e878bf214 to your computer and use it in GitHub Desktop.
Enqueue tasks on unity main thread
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading.Tasks;
public class ThreadController : MonoBehaviour
{
private static ThreadController _instance = null;
private static readonly Queue<Action> _executionQueue = new Queue<Action>();
public static ThreadController Instance()
{
if (!Exists())
{
throw new Exception("ThreadController needs to be added to your scene.");
}
return _instance;
}
void Awake()
{
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(this.gameObject);
}
}
public void Update()
{
lock (_executionQueue)
{
while (_executionQueue.Count > 0)
{
_executionQueue.Dequeue().Invoke();
}
}
}
public void Enqueue(IEnumerator action)
{
lock (_executionQueue)
{
_executionQueue.Enqueue(() => {
StartCoroutine(action);
});
}
}
public void Enqueue(Action action)
{
Enqueue(ActionWrapper(action));
}
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 callback)
{
callback();
yield return null;
}
public static bool Exists()
{
return _instance != null;
}
void OnDestroy()
{
_instance = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment