UniTask提供了很多异步方法,如Resources.LoadAsync,UniTask.NextFrame,UniTask.WaitUntil,按钮事件button.OnClickAsync等
当没有内置方法时,我们希望能将自己的回调方法改写为await的形式。
比如将PlayableDirector的stopped回调改写成await,实现如下代码。
private async UniTask PlayAndDebug()
{
await _director.OnStoppedAsync();
Debug.Log("director stopped,do something else");
}
原理:通过实现IUniTaskSource和IUniTaskSource
public class PlayableDirectorAsyncHandler:IUniTaskSource
{
static Action<object> cancellationCallback = CancellationCallback;
private CancellationToken cancellationToken;
private CancellationTokenRegistration registration;
private UniTaskCompletionSourceCore<bool> core;
bool isDisposed;
bool callOnce;
private PlayableDirector _director;
public PlayableDirectorAsyncHandler(PlayableDirector director,CancellationToken cancellationToken, bool callOnce)
{
this.cancellationToken = cancellationToken;
if (cancellationToken.IsCancellationRequested)
{
isDisposed = true;
return;
}
this.callOnce = callOnce;
_director = director;
_director.stopped += OnDirectorStopped;
if (cancellationToken.CanBeCanceled)
{
registration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
}
TaskTracker.TrackActiveTask(this, 3);
}
static void CancellationCallback(object state)
{
var self = (PlayableDirectorAsyncHandler)state;
self.Dispose();
}
private void OnDirectorStopped(PlayableDirector obj)
{
core.TrySetResult(true);
}
public void Dispose()
{
if (!isDisposed)
{
isDisposed = true;
TaskTracker.RemoveTracking(this);
registration.Dispose();
_director.stopped -= OnDirectorStopped;
core.TrySetCanceled(cancellationToken);
}
}
public UniTask OnInvokeAsync()
{
core.Reset();
if (isDisposed)
{
core.TrySetCanceled(this.cancellationToken);
}
return new UniTask(this, core.Version);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public void GetResult(short token)
{
try
{
core.GetResult(token);
}
finally
{
if (callOnce)
{
Dispose();
}
}
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
}
最后实现一个扩展方法
public static class UniTaskAsyncExtensions
{
public static UniTask OnStoppedAsync(this PlayableDirector director,CancellationToken cancellationToken = default,bool callOnce = true)
{
return new PlayableDirectorAsyncHandler(director,cancellationToken, callOnce).OnInvokeAsync();
}
}
扩展完成。
标签:cancellationToken,PlayableDirector,为例,core,await,director,UniTask,public From: https://www.cnblogs.com/terrynoya/p/16783616.html