Files

119 lines
3.8 KiB
C#

using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
namespace io.github.hatayama.uLoopMCP
{
/// <summary>
/// Timer-based asynchronous delay for Unity Editor
/// Provides async/await support for time-based delays that work regardless of Unity Editor state
/// </summary>
public static class TimerDelay
{
/// <summary>
/// Wait for the specified number of milliseconds
/// </summary>
/// <param name="milliseconds">Milliseconds to wait</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Awaitable task</returns>
public static Task Wait(int milliseconds, CancellationToken cancellationToken = default)
{
if (milliseconds <= 0)
{
return Task.CompletedTask;
}
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
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;
}
/// <summary>
/// Wait for the specified number of milliseconds, then execute action on main thread
/// </summary>
/// <param name="milliseconds">Milliseconds to wait</param>
/// <param name="action">Action to execute on main thread</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Awaitable task</returns>
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<bool> tcs = new TaskCompletionSource<bool>();
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;
}
}
}