在 C# 中,await
和 Wait()
都与异步编程相关,但它们的用途和行为有显著区别:
1. await
(关键字)
- 用途:用于异步等待一个
Task
或Task<T>
完成,非阻塞当前线程。 - 特点:
- 只能在标记为
async
的方法中使用。 - 不会阻塞调用线程(如 UI 线程),线程可以自由处理其他任务。
- 自动解包
Task<T>
的结果(直接返回T
类型)。 - 是编译器的语法糖,底层通过状态机实现异步逻辑。
- 只能在标记为
- 示例:
async Task DownloadAsync()
{
HttpClient client = new HttpClient();
string result = await client.GetStringAsync("https://example.com"); // 非阻塞等待
Console.WriteLine(result);
}
2. Wait()
(方法)
- 用途:同步阻塞当前线程,直到
Task
完成。 - 特点:
- 是
Task
的实例方法(如task.Wait()
)。 - 会阻塞当前线程,可能导致死锁(尤其在 UI 线程或 ASP.NET 上下文中)。
- 不自动解包结果(需手动通过
task.Result
获取)。 - 通常应避免使用,除非在控制台程序或明确需要同步的场景。
- 是
- 示例:
void DownloadSync()
{
HttpClient client = new HttpClient();
var task = client.GetStringAsync("https://example.com");
task.Wait(); // 阻塞线程,可能引发死锁
Console.WriteLine(task.Result);
}
核心区别总结
特性 | await |
Wait() |
---|---|---|
线程行为 | 非阻塞(释放线程) | 阻塞当前线程 |
使用场景 | 异步方法(async ) |
同步上下文 |
结果获取 | 自动解包 Task<T> |
需手动访问 Result |
死锁风险 | 无 | 高(尤其在 UI/ASP.NET 中) |
推荐程度 | ✅ 首选 | ❌ 尽量避免 |
何时用哪个?
- 用
await
:
所有异步编程场景(如 IO 操作、网络请求、UI 响应等)。 - 用
Wait()
:
极少数需强制同步的场景(如控制台程序的Main
方法),且需确保无死锁风险。
附加说明
-
await
的底层机制:
编译器会将await
转换为状态机,实现异步回调,无需手动处理Task
的延续(ContinueWith
)。 -
Wait()
的替代方案:
若需同步等待,可考虑GetAwaiter().GetResult()
(仍需谨慎),或重构为完全异步。