在 C# 中使用 async
和 await
时,有一些关键点需要注意:
-
异步方法命名:
- 通常建议将异步方法的名称以
Async
结尾,以便清楚地表明方法是异步的。例如:GetDataAsync
。
- 通常建议将异步方法的名称以
-
async
关键字:- 在方法签名中使用
async
关键字,表明该方法是异步的。注意,async
方法可以包含await
表达式,但不一定必须有await
。
- 在方法签名中使用
-
返回类型:
- 异步方法通常返回
Task
或Task<T>
类型。如果方法不返回值,则返回Task
,如果返回特定类型的值,则返回Task<T>
。 - 例外:
async void
仅用于事件处理程序中,不应在其他情况下使用,因为它不能被调用者等待,也无法捕获异常。
- 异步方法通常返回
-
await
表达式:await
用于等待异步操作完成,并返回其结果。await
后的操作将异步执行,但它并不阻塞线程,而是将控制权返回给调用者,直到任务完成。- 只能在标记为
async
的方法或 lambda 表达式中使用await
。
-
避免死锁:
- 在 UI 应用程序中,避免在同步上下文中使用
Wait()
或Result
来阻塞异步操作。这可能会导致死锁,因为 UI 线程可能在等待操作完成,而操作又在等待 UI 线程空闲。
- 在 UI 应用程序中,避免在同步上下文中使用
-
异常处理:
- 异常会在
await
时被抛出,因此可以用try-catch
包裹await
语句来捕获异常。 - 如果方法返回
Task
或Task<T>
,调用者也可以在等待任务时处理异常。
- 异常会在
-
性能和并行性:
- 虽然
async
和await
提供了一种简化异步编程的方式,但它们并不会自动带来并行性。如果需要并行执行多个任务,应该显式地启动多个任务,并使用Task.WhenAll
等方法等待它们。
- 虽然
-
ConfigureAwait(false)
的使用:- 在库代码中,通常使用
ConfigureAwait(false)
来避免捕获当前同步上下文,这样可以避免某些不必要的上下文切换,提升性能。
- 在库代码中,通常使用
通过注意这些关键点,能够更有效地利用 async
和 await
进行异步编程,同时避免常见的陷阱。