Awaitable 代码示例参考
Solve common asynchronous programming problems with a reference of Awaitable code examples.
阅读时间4 分钟最后更新于 1 个月前
本参考中的示例演示了编写异步代码时遇到的常见情况的 解决方案。
Awaitable异步测试
[UnityTest]public IEnumerator SomeAsyncTest(){ async Awaitable TestImplementation(){ // test something with async / await support here }; return TestImplementation();}
框架协同程序
您可以使用 类中与框架相关的异步方法来创建异步 Unity 协同程序,以替代基于迭代器的协同程序:
Awaitableasync Awaitable SampleSchedulingJobsForNextFrame(){ // Wait until end of frame to avoid competing over resources with other Unity subsystems await Awaitable.EndOfFrameAsync(); var jobHandle = ScheduleSomethingWithJobSystem(); // Let the job execute while the next frame starts await Awaitable.NextFrameAsync(); jobHandle.Complete(); // Use results of computation}JobHandle ScheduleSomethingWithJobSystem(){ ...}
协程等待
public static async AwaitableUntil(Func<bool> condition, CancellationTokenSource cancellationToken){ while(!condition()){ cancellationToken.ThrowIfCancellationRequested(); await Awaitable.NextFrameAsync(); }}
然后,您可以按如下方式传入取消令牌:
cancellationTokenSource = new CancellationTokenSource();currentTask = AwaitableUntil(myCondition, cancellationTokenSource.Token);
异步加载资源
您可以 异步资源加载操作,使其不会阻塞主线程:
awaitpublic async Awaitable Start(){ // Load texture resource asynchronously var operation = Resources.LoadAsync("my-texture"); // Return control to the main thread while the resource loads await operation; var texture = operation.asset as Texture2D;}
编译
您可以在同一方法中 多个不同的 兼容类型:
awaitawaitpublic async Awaitable Start(){ await CallSomeThirdPartyAPIReturningDotnetTask(); await Awaitable.NextFrameAsync(); await SceneManager.LoadSceneAsync("my-scene"); await SomeUserCodeReturningAwaitable(); ...}
在 .NET Task 中封装 Awaitable
要解决 的一些限制,可以将其封装在 .NET 中。这会产生分配开销,但允许从 API 访问 和 等方法。为此,您可以编写自己的自定义 扩展方法,如下所示:
AwaitableTaskTaskWhenAllWhenAnyAsTask// Implement custom AsTask extension methods to wrap Awaitable in Taskpublic static class AwaitableExtensions { public static async Task AsTask(this Awaitable a) { await a; } public static async Task<T> AsTask<T>(this Awaitable<T> a) { return await a; } }
多次等待结果
AwaitableTaskAwaitableawaitAwaitableAwaitable不安全版本
以下代码不安全,将导致异常和死锁:
async Awaitable Bar(){ var taskWithResult = SomeAwaitableReturningFunction(); var awaitOnce = await taskWithResult; // Do something // The following will cause errors because at this point taskWithResult has already been pooled back var awaitTwice = await taskWithResult; }
安全版本
这种情况下,您能够以分配开销将 Awaitable 封装在 Task 中。然后,可以安全地多次等待 :
Task// Implement custom AsTask extension methods to wrap Awaitable in Taskpublic static class AwaitableExtensions { public static async Task AsTask(this Awaitable a) { await a; } public static async Task<T> AsTask<T>(this Awaitable<T> a) { return await a; } }async Awaitable Bar(){ var taskWithResult = SomeAwaitableReturningFunction(); // Wrap the returned Awaitable in a Task var taskWithResultAsTask = taskWithResult.AsTask(); // The task can now be safely awaited multiple times, at the cost of allocating var awaitOnce = await taskWithResultAsTask; // Do something var awaitTwice = await taskWithResultAsTask; }