async 修饰的方法为异步方法。Task / Task<TResult> / voidawait 表达式;若无 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 许可协议。转载请注明出处!