C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > Task.Wait()、Task.Result、Task.GetAwaiter().GetResult()

C#中Task.Wait()、Task.Result、Task.GetAwaiter().GetResult()区别

作者:无风听海

本文主要介绍了C#中Task.Wait()、Task.Result、Task.GetAwaiter().GetResult()区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、概念对比

方法/属性阻塞线程调用 TaskAwaiter continuation异常处理典型用途
Task.Wait()✅ 阻塞调用线程❌ 不触发 continuation抛 AggregateException同步等待 Task 完成,不关心结果
Task.Result✅ 阻塞调用线程❌ 不触发 continuation抛 AggregateException 包含 Task 异常同步获取 Task 结果
Task.GetAwaiter().GetResult()✅ 阻塞调用线程❌ 不触发 continuation直接抛原始异常(不包 AggregateException)内部 await/框架调用同步获取 Task 结果,更精确异常

二、底层机制分析

1、 Task.Wait()

public void Wait() {
    if (!IsCompleted)
        WaitHelper.Wait(this, Timeout.Infinite, cancellationToken: default);
}

2、Task.Result

public T Result {
    get {
        Wait();           // 调用同步等待
        return GetResult(); // 返回 Task<T> 结果
    }
}

3、 Task.GetAwaiter().GetResult()

var awaiter = task.GetAwaiter();
awaiter.GetResult();

三、线程行为对比

Caller Thread
 ├─ Task.Wait() / Task.Result / GetAwaiter().GetResult()
 |    -> 阻塞当前线程
Task completes (ThreadPool/IOCP)
 ├─ Task signals wait handle
Caller Thread unblocks
 ├─ Wait() 返回 / Result 返回 / GetResult() 返回或抛异常

注意:无论哪种方式,continuation 不会在阻塞线程上执行

  • async/await 的 continuation 依赖 OnCompleted / SynchronizationContext 调度
  • 直接同步阻塞方法绕过了这些机制

四、异常处理差异

方法异常类型包装情况
Task.Wait()Task 异常AggregateException
Task.ResultTask 异常AggregateException
Task.GetAwaiter().GetResult()Task 异常原始异常(unwrap)

⚠️ 这是为什么 GetAwaiter().GetResult() 更常在库内部使用,因为它可以避免额外的 AggregateException 包装,保持异常原样。

五、潜在风险

  1. 死锁

    • 在 UI 线程调用 Wait() / Result,而 Task continuation 捕获 SynchronizationContext → continuation 无法执行 → 死锁。
  2. 线程阻塞

    • 阻塞调用线程,浪费资源,ThreadPool 扩展可能触发饥饿。

六、总结

  1. Task.Wait() → 阻塞等待,无返回值,异常 AggregateException
  2. Task.Result → 阻塞等待,返回结果,异常 AggregateException
  3. Task.GetAwaiter().GetResult() → 阻塞等待,返回结果或抛原始异常,内部 await/框架常用
  4. 都不触发 continuation,阻塞线程可能导致死锁
  5. async/await 才是非阻塞、自动调度 continuation 的机制

到此这篇关于C#中Task.Wait()、Task.Result、Task.GetAwaiter().GetResult()区别的文章就介绍到这了,更多相关Task.Wait()、Task.Result、Task.GetAwaiter().GetResult()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文