从 C# 基础到掌握 — 第 8 集
使用async和await构建异步任务
该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。
在等待网络或文件操作时阻塞线程也可能冻结屏幕和其他操作。 async 和await 表示等待任务,以便可以连续执行。
返回任务
async Task<PlayerData> LoadPlayerAsync(
string url,
CancellationToken cancellationToken)
{
using HttpResponseMessage response =
await httpClient.GetAsync(url, cancellationToken);
response.EnsureSuccessStatusCode();
PlayerData? data = await response.Content
.ReadFromJsonAsync<PlayerData>(cancellationToken);
return data ?? throw new InvalidDataException("Player data is empty");
}
当您遇到等待时,您可以稍后继续执行其余代码,而不是保留当前线程直到任务完成。 异步方法基本上返回一个任务,以便调用者可以观察完成和失败。
取消转发
using var source = new CancellationTokenSource(TimeSpan.FromSeconds(5));
try
{
PlayerData data = await LoadPlayerAsync(url, source.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Loading canceled");
}
Cancel 不是强制终止线程的函数。 请求任务验证令牌并在安全点中止的合约。
等待多个任务
Task<ItemData> itemTask = LoadItemsAsync(token);
Task<QuestData> questTask = LoadQuestsAsync(token);
await Task.WhenAll(itemTask, questTask);
ItemData items = await itemTask;
QuestData quests = await questTask;
相互不依赖的等待任务可以先启动,然后一起等待。 简单地将 CPU 计算标记为异步并不会自动使其成为并行计算。
避免流动
使用Task的.Result或.Wait()进行同步等待可能会阻塞线程或创建死锁,具体取决于执行环境。 最好尽可能继续异步调用路径。
除事件处理程序外,应避免使用 async void,因为调用者无法等待完成和异常。 异步代码的关键不是添加关键字,而是向调用者传达完成、失败和取消的流程。