0

0

c# 避免在异步方法中使用 .Result 或 .Wait() 的原因

畫卷琴夢

畫卷琴夢

发布时间:2026-01-01 05:39:31

|

382人浏览过

|

来源于php中文网

原创

.Result 和 .Wait() 在 UI 或 ASP.NET 同步上下文中会死锁,因它们阻塞线程导致 await 无法回调;应全程使用 async/await,必要时用 ConfigureAwait(false) 避免上下文捕获,禁用同步等待。

c# 避免在异步方法中使用 .result 或 .wait() 的原因

为什么 .Result.Wait() 在 async 方法里会死锁

在 UI 线程(如 WinForms/WPF)或 ASP.NET 同步上下文(如旧版 .NET Framework 的 AspNetSynchronizationContext)中,await 默认会尝试回到原上下文继续执行。而 .Result.Wait() 会阻塞当前线程,导致上下文线程被占住;当异步操作完成、试图回调回该线程时,就卡住了——线程在等任务完成,任务又在等线程空闲,形成典型死锁。

替代方案:用 await 替代同步等待

最直接的解法是把调用链全部改为 async/await,让异步流自然穿透。常见错误写法和修正如下:

  • ❌ 错误:var data = GetJsonAsync().Result;(在 async Task 方法里也禁用)
  • ✅ 正确:var data = await GetJsonAsync();
  • 如果入口方法不能改(如某些事件处理函数签名固定),优先升级为 async void(仅限事件处理器),但避免在其他地方用 async void
  • 极少数必须同步等待的场景(如 Main 方法、全局初始化),可考虑 GetAwaiter().GetResult(),它不捕获同步上下文,但依然会阻塞线程,仅作兜底

ConfigureAwait(false) 能缓解但不能根治

ConfigureAwait(false) 可以让 await 不尝试回到原始上下文,从而避免 UI/ASP.NET 中的死锁。但它只对 await 生效,对 .Result.Wait() 完全无效——这两个方法本身就会强制同步阻塞,跟配置无关。

示例:

TTSMaker
TTSMaker

TTSMaker是一个免费的文本转语音工具,提供语音生成服务,支持多种语言。

下载
var task = DoWorkAsync();
// 即使下面用了 ConfigureAwait,.Result 仍会死锁
// ❌ var result = task.ConfigureAwait(false).GetAwaiter().GetResult(); // 错!还是阻塞
// ✅ var result = await task.ConfigureAwait(false); // 对

性能与可观测性代价不止是死锁

即使在没有同步上下文的环境(如 .NET Core 控制台程序),滥用 .Result.Wait() 仍有隐患:

  • 线程池线程被长期占用,降低并发吞吐能力
  • 异常包装成 AggregateException,堆信息被截断,调试困难
  • 无法参与 async 的取消传播(CancellationToken 会被忽略)
  • 某些库(如 Entity Framework Core)内部有 async-only 路径,强行同步调用可能触发未定义行为

真正难处理的不是“怎么让它跑起来”,而是“为什么它偶尔卡住、有时抛奇怪异常、上线后吞吐骤降”——这些问题往往都藏在某个不起眼的 .Result 调用里。

相关专题

更多
javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

173

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

92

2025.11.27

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

366

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

561

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

366

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

561

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

471

2023.08.10

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

3

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

1

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.1万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号