async
修饰的方法为异步方法。Task
/ Task<TResult>
/ void
await
表达式;若无 await
,方法被视为同步返回已完成的 Task
。csharppublic async Task<int> LoadDataAsync()
{
const int DelayMilliseconds = 1000; // 避免硬编码
await Task.Delay(DelayMilliseconds);
return 42;
}
await
会异步挂起当前方法,直到其等待的 Task
完成;完成后继续执行挂起处之后的代码;async
方法转换为状态机(生成私有结构体/类,包含状态字段与 MoveNext()
);Task
:无返回值的异步方法;Task<TResult>
:有结果的异步方法;async void
:仅限事件处理器;无法被 await
,异常也不易捕获,勿用于业务逻辑。csharppublic async Task UseAsyncVoidWrong()
{
// 反例:不要在业务逻辑里用 async void
}
Task
中,通过 await
抛出到调用点。CancellationToken
,由调用方传入。csharppublic async Task DownloadAsync(CancellationToken ct)
{
try
{
await Task.Run(() =>
{
// 模拟工作;实际代码里要定期检查 ct.IsCancellationRequested
for (var i = 0; i < 3; i++)
{
ct.ThrowIfCancellationRequested();
System.Threading.Thread.Sleep(100);
}
}, ct);
}
catch (OperationCanceledException)
{
// 取消逻辑
throw;
}
}
Task.Wait()
/ .Result
)SynchronizationContext
的线程(如 UI/Unity 主线程)上阻塞等待可能导致死锁。await
贯穿到底**,不要混用阻塞等待,这样后续非常不利于代码的调试和维护csharp// 反例:可能死锁
// var r = SomeAsync().Result; // 或 SomeAsync().Wait();
MoveNext()
(核心调度逻辑)SetStateMachine()
(调试器支持)async/await
语法完全兼容;UniTask
/ UniTask<T>
;csharpusing Cysharp.Threading.Tasks;
public class Example
{
public async UniTask LoadDataAsync()
{
await UniTask.Delay(1000); // 主线程异步等待 1 秒;
UnityEngine.Debug.Log("完成");
}
public async UniTask<int> GetNumberAsync()
{
await UniTask.Yield(); // 下一帧继续执行;
return 42;
}
}
特性 | Task | UniTask |
---|---|---|
类型 | class(引用类型); | struct(值类型); |
GC 分配 | 有 GC 压力; | 几乎无 GC; |
返回值 | Task / Task; | UniTask / UniTask; |
默认调度 | .NET 线程池 或 IOCP; | Unity PlayerLoop(主线程); |
csharppublic async UniTask ExampleAsync()
{
UnityEngine.Debug.Log("帧1 Update 阶段");
await UniTask.Yield(PlayerLoopTiming.LateUpdate); // 下一帧 LateUpdate 阶段恢复;
UnityEngine.Debug.Log("帧2 LateUpdate 阶段");
}
csharppublic async UniTask<int> ExampleMultiThreadAsync()
{
await UniTask.SwitchToThreadPool(); // 切到线程池;
int result = HeavyCalculation(); // 子线程执行;
await UniTask.SwitchToMainThread(); // 切回主线程;
return result;
}
csharppublic async UniTask ExampleWhenAll()
{
var task1 = UniTask.Delay(1000);
var task2 = UniTask.Delay(2000);
await UniTask.WhenAll(task1, task2);
UnityEngine.Debug.Log("两个任务都完成");
}
本文作者:xuxuxuJS
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!