传统的异步编程方式很复杂,直到 C# 5 引入了 async 编程模式。
.NET 内置的异步方法
async 和 await 关键字
async 和 await 是 C# 异步编程的核心,由它们定义的方法称为异步方法。
异步方法示例:
// Three things to note in the signature:
// - The method has an async modifier.
// - The return type is Task or Task<T>.
// Here, it is Task<int> because the return statement returns an integer.
// - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
什么是异步方法
方法签名包括 async 修饰符
约定方法名以 Async 为后缀
返回类型为以下几种之一
- Task
- Task
- void
- 方法内部至少包含一句 await 表达式:
string urlContents = await getStringTask;
- await 表达式的意思是:方法在此处需要等待异步操作完成后才能继续向下执行。同时方法将被挂起,控制流返回给方法的调用者
异步编程的核心就是 Task 和 Task
在 C# 中一个 Task 对象可以看作一个需要继续执行的操作,一个 Task
I/O 绑定异步操作示例:从 Web Service 下载数据
private readonly HttpClient _httpClient = new HttpClient();
downloadButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI as the request
// from the web service is happening.
//
// The UI thread is now free to perform other work.
var stringData = await _httpClient.GetStringAsync(URL);
DoSomethingWithData(stringData);
};
CPU 绑定异步操作示例:执行计算
使用 Task.Run 来启动一个后台线程用于执行 CPU 绑定的操作。
private DamageResult CalculateDamageDone()
{
// Code omitted:
//
// Does an expensive calculation and returns
// the result of that calculation.
}
calculateButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI while CalculateDamageDone()
// performs its work. The UI thread is free to perform other work.
var damageResult = await Task.Run(() => CalculateDamageDone());
DisplayDamage(damageResult);
};
.NET 类库内置的异步方法
通过 Async 后缀和返回类型为 Task(Task)来识别内置的异步方法。
网络操作相关的:
HttpClient:发送 HTTP 请求,接收 HTTP 响应
WebClient:收发数据
I/O 操作相关的:
StreamWrite
StreamReader
XmlReader