异步
异步是编程中非常重要的概念, C# 实现异步的原理是由编译器将代码转换为状态机,跟踪代码执行到 await 时暂停以及后台作业完成时继续执行。
如果需要 I/O 绑定(例如从网络请求数据、访问数据库或读取和写入到文件系统),则需要利用异步编程。 还可以使用 CPU 绑定代码(例如执行成本高昂的计算),对编写异步代码而言,这是一个不错的方案。
下面举例 CPU 绑定代码 的异步情况:
主线程:触发按键执行后台任务 -> 倒计时 -> 按任意键退出程序
后台线程:进入 -> 倒计时 -> 退出
Task 类
创建一个异步任务并执行
public static async Task SimpleWriteAsync()
{
string filePath = "simple.txt";
string text = $"Hello World!";
await File.WriteAllTextAsync(filePath, text);
}
static void Main()
{
SimpleWriteAsync().Wait();
}
对于 I/O 绑定代码,等待一个在 async 方法中返回 Task 或 Task 的操作。
对于 CPU 绑定代码,等待一个使用 Task.Run 方法在后台线程启动的操作。
using System;
using System.Threading.Tasks;
using System.Threading;
// 1 声明委托
public delegate void onCountTime();
class Program
{
// 模拟一些耗时的复杂操作
static string CountTimer(string s, int start, int dt)
{
int counter = start;
while (counter > 0)
{
Console.WriteLine(s + counter);
Thread.Sleep(dt);
counter--;
}
return s + "计时结束";
}
// 4 异步的事件处理函数
static async void OnClicked()
{
string result = "";
Console.WriteLine("async OnClicked start");
// 4.1 等待异步任务 直到任务结束
await Task.Run(() => { result = CountTimer("task:", 3, 2000); });
// 4.2 打印结果
Console.WriteLine(result);
Console.WriteLine("async OnClicked end");
}
static void Main()
{
// 实例化一个按钮类的实例
Button btn = new Button();
// 5 为按钮的点击绑定事件处理函数
btn.Clicked += OnClicked;
// 6 (模拟用户按下按键)手动呼叫事件
btn.CallClicked();
// 7 在后台处理按键按下的任务 当前线程继续执行
Console.WriteLine(CountTimer("main:", 3, 500));
Console.WriteLine("pressed any key to exit");
// 按下任意键退出程序
Console.ReadKey();
}
// 按钮类
class Button
{
// 2 声明事件
public event onCountTime Clicked;
// 3 呼叫用户按下按键的事件
public void CallClicked()
{
Clicked?.Invoke();
}
}
}
// 打印结果:
async OnClicked start
task:3
main:3
main:2
main:1
main:计时结束
pressed any key to exit
task:2
task:1
task:计时结束
async OnClicked end