C# 中的 async
和 await
关键字是用于实现异步编程的重要工具,它们简化了编写和维护非阻塞代码的过程。以下是对这两个关键字用法的简要说明:
async 关键字
-
定义异步方法 :在方法声明前使用
async
关键字,表示该方法是一个异步方法。它通常会返回一个Task
或Task<T>
类型(对于有返回值的方法)。public async Task<int> GetAsyncResultAsync()
{
// ...
}
await 关键字
- 等待异步操作完成 :在异步方法内部,当你需要等待一个异步操作(如网络请求、文件读写等)完成时,可以对返回
Task
或Task<T>
的调用使用await
关键字。
cs
public async Task<int> GetAsyncResultAsync()
{
var result = await SomeAsynchronousOperation();
// 当SomeAsynchronousOperation()完成时,控制流将返回到这里继续执行。
return result;
}
private async Task<int> SomeAsynchronousOperation()
{
// 这里模拟一个耗时的操作...
await Task.Delay(1000); // 延迟1秒
return 42; // 返回结果
}
行为特点:
- 当遇到
await
表达式时,当前方法(称为awaiter方法)会暂停执行,并立即返回一个未完成的Task
给调用者。这意味着调用者不会被阻塞,而是可以继续执行其他任务。 - 然后,线程池中的线程会被释放回线程池,而不是被阻塞等待异步操作完成。
- 当异步操作完成后,系统会安排一个线程(可能是原来线程也可能是新获取的线程,取决于上下文是否可调度)来执行
await
后面的语句。 - 如果异步方法有返回值,最终的结果将会封装到
Task<T>
中。
注意点:
- 异步方法中不应包含阻塞性操作,因为这样会浪费异步带来的性能优势。
- 异步方法默认不会启动任何操作,直到该方法被调用并await其返回的任务。
- 使用async/await时,应尽量避免嵌套过多层,以保持代码简洁且易于理解。
async
关键字用于标记异步方法,await
用于等待异步操作的完成。- 使用
await
时,需要确保等待的操作是返回Task
或Task
的子类。 - 异步方法中可以使用
try/catch
块来处理异常。 - 避免在异步方法中使用阻塞操作,例如
Thread.Sleep
,因为它会阻塞整个线程。
通过这种方式,C# 的 async
和 await
能够帮助开发者编写出高效、响应性好的应用程序,特别是在处理I/O密集型操作时。可以使异步代码更加清晰和易于理解,提高程序的性能和响应性。
注意:使用async
和await
时,要确保不要在非异步方法中使用它们,否则编译器会报错。
同样,如果一个异步方法不使用await
来调用另一个异步方法,那么这个方法就不是真正意义上的异步方法,因为它会立即执行并完成,而不是等待内部的异步操作完成。