C# 异步编程方法 C#如何使用async和await

来源:这里教程网 时间:2026-02-21 17:39:36 作者:

async 方法必须返回 Task 或 Task

不满足这个条件的

async
方法在编译时就会报错,比如返回
void
(除事件处理器外)或
int
。这是最基础也最容易忽略的约束。

async Task
用于无返回值的异步操作,如
async Task SaveAsync()
async Task<string></string>
用于有返回值的异步操作,调用后可用
await
获取
string
结果
避免写
async void DoSomething()
—— 无法被等待、异常会直接崩掉线程、难以测试

await 只能在 async 方法内部使用

试图在普通方法里写

await SomeAsyncMethod()
会触发编译错误 CS4032:“The 'await' operator can only be used within an async method.”

不是“加个
async
就行”,还要同步改返回类型(见上一条)
如果调用链顶端是 UI 事件(如按钮点击),可合法用
async void
,但仅限这一层
Web API 控制器中应始终用
async Task<iactionresult></iactionresult>
,而非
async void

不要用 .Result 或 .Wait() 阻塞异步方法

在 ASP.NET Core 或 WinForms 中调用

task.Result
task.Wait()
极易引发死锁,尤其在有同步上下文(SynchronizationContext)的环境里。

典型死锁现象:UI 线程卡住 / HTTP 请求永远不返回 / 日志停在某一行不动 替代方案:把调用点也改成
async
+
await
,让整个调用链异步穿透
实在无法改(如老代码或第三方同步接口),可用
Task.Run(() => SomeAsyncMethod()).Result
绕过上下文,但这是权宜之计,不是设计选择

ConfigureAwait(false) 在类库中值得默认添加

在非 UI、非 ASP.NET 传统管线(如 .NET Core Web API、类库、工具函数)中,

await task.ConfigureAwait(false)
能避免不必要的上下文捕获,提升性能并防止潜在死锁。

ASP.NET Core 默认无 SynchronizationContext,所以
ConfigureAwait(false)
影响不大,但加了也没坏处
在 NuGet 类库项目中建议统一加上,避免下游使用者踩坑 UI 层(WPF/WinForms)需要更新控件时,不能加
ConfigureAwait(false)
,否则会抛出跨线程访问异常
public async Task<string> FetchDataAsync()
{
    var response = await httpClient.GetAsync("https://api.example.com/data")
        .ConfigureAwait(false); // 类库中推荐
    return await response.Content.ReadAsStringAsync()
        .ConfigureAwait(false);
}
异步的本质不是“多线程”,而是“不阻塞当前线程”。很多人一上来就想着开新线程,反而绕远了。真正容易出问题的地方,往往藏在返回类型和上下文切换这两处。

相关推荐