using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
namespace io.github.hatayama.uLoopMCP
{
///
/// Timer-based asynchronous delay for Unity Editor
/// Provides async/await support for time-based delays that work regardless of Unity Editor state
///
public static class TimerDelay
{
///
/// Wait for the specified number of milliseconds
///
/// Milliseconds to wait
/// Cancellation token
/// Awaitable task
public static Task Wait(int milliseconds, CancellationToken cancellationToken = default)
{
if (milliseconds <= 0)
{
return Task.CompletedTask;
}
TaskCompletionSource tcs = new TaskCompletionSource();
Timer timer = null;
timer = new Timer(_ =>
{
timer?.Dispose();
timer = null;
if (!cancellationToken.IsCancellationRequested)
{
tcs.SetResult(true);
}
else
{
tcs.SetCanceled();
}
}, null, milliseconds, Timeout.Infinite);
// Handle cancellation
if (cancellationToken.CanBeCanceled)
{
cancellationToken.Register(() =>
{
timer?.Dispose();
timer = null;
tcs.TrySetCanceled();
});
}
return tcs.Task;
}
///
/// Wait for the specified number of milliseconds, then execute action on main thread
///
/// Milliseconds to wait
/// Action to execute on main thread
/// Cancellation token
/// Awaitable task
public static Task WaitThenExecuteOnMainThread(int milliseconds, Action action, CancellationToken cancellationToken = default)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
if (milliseconds <= 0)
{
EditorApplication.delayCall += () => action();
return Task.CompletedTask;
}
TaskCompletionSource tcs = new TaskCompletionSource();
Timer timer = null;
timer = new Timer(_ =>
{
timer?.Dispose();
timer = null;
if (!cancellationToken.IsCancellationRequested)
{
EditorApplication.delayCall += () =>
{
try
{
action();
tcs.SetResult(true);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
};
}
else
{
tcs.SetCanceled();
}
}, null, milliseconds, Timeout.Infinite);
// Handle cancellation
if (cancellationToken.CanBeCanceled)
{
cancellationToken.Register(() =>
{
timer?.Dispose();
timer = null;
tcs.TrySetCanceled();
});
}
return tcs.Task;
}
}
}