using System;
using System.Runtime.CompilerServices;
using Windows.UI.Core;
using Windows.UI.Xaml;
namespace OwlCore.WinUI.Threading
{
///
/// Builds a new .
///
public class UiTaskMethodBuilder
{
private readonly CoreDispatcher _dispatcher;
///
/// Creates a new instance of .
///
///
public UiTaskMethodBuilder(CoreDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
///
/// Starts the async machine.
///
public void Start(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
if (!_dispatcher.HasThreadAccess)
{
var action = new Action(stateMachine.MoveNext);
_ = _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
}
else
{
stateMachine.MoveNext();
}
}
///
/// Creates a singleton of .
///
///
public static UiTaskMethodBuilder Create()
{
return new UiTaskMethodBuilder(Window.Current.Dispatcher);
}
///
/// This one is pretty obscure, I’m not even sure when it’s supposed to be called. We’re not going to need it so we’ll leave it empty.
///
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
}
///
/// Called at the end of the async method, to set the result. We can simply map to the TaskCompletionSource.
///
public void SetResult()
{
Task.Promise.SetResult(new object());
}
///
/// Called at the end of the async method, to set an exception. We can simply map to the TaskCompletionSource.
///
///
public void SetException(Exception exception)
{
Task.Promise.SetException(exception);
}
///
/// Exposes the instance of our custom UI task that will be returned by the async method
///
public UiTask Task { get; } = new UiTask();
///
/// Called to set the completion state.
///
public void AwaitOnCompleted(
ref TAwaiter awaiter,
ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(ResumeAfterAwait(stateMachine));
}
///
/// Called to set the completion state, if the awaiter implements ICriticalNotifyCompletion.
///
public void AwaitUnsafeOnCompleted(
ref TAwaiter awaiter,
ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.UnsafeOnCompleted(ResumeAfterAwait(stateMachine));
}
private Action ResumeAfterAwait(TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
return () =>
{
if (!_dispatcher.HasThreadAccess)
{
var action = new Action(stateMachine.MoveNext);
_ = _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
}
else
{
stateMachine.MoveNext();
}
};
}
}
}