一般来说我们写的控制台程序都只使用了一个线程,从第一条语句按顺序执行到最后一条。但在很多的情况下,这种简单的模型会在性能或用户体验上不好,这也叫同步方法。
例如:服务器要同时处理来自多个客户端程序的请求,又要等待数据库和其它设备的响应,这将严重影响性能。程序不应该将时间浪费在响应上,而要在等待的同时执行其它任务!
现在我们开始进入异步编程。**在异步程序中,代码不需要按照编写时的顺序执行。**这时我们需要用到 C# 5.0 引入的 async/await 来构建异步方法。
异步方法:在执行完成前立即返回调用方法,执行其它方法。
async/await 结构可分成三部分:
(1)调用方法:该方法调用异步方法,然后在异步方法执行其任务的时候继续执行;
(2)异步方法:该方法异步执行工作,然后立刻返回到调用方法;
(3)await 表达式:用于异步方法内部,指出需要异步执行的任务。一个异步方法可以包含多个 await 表达式(不存在 await 表达式的话 IDE 会发出警告)。
在遇到awiat关键字之前,程序是按照代码顺序自上而下以同步方式执行的。
在遇到await关键字之后,系统做了以下工作:
异步方法将被挂起
将控制权返回给调用者
使用线程池中的线程(而非额外创建新的线程)来计算await表达式的结果,所以await不会造成程序的阻塞
完成对await表达式的计算之后,若await表达式后面还有代码则由执行await表达式的线程(不是调用方所在的线程)继续执行这些代码
定义一个异步方法应满足以下几点:
使用async关键字来修饰方法
在异步方法中使用await关键字(不使用编译器会给出警告但不报错),否则异步方法会以同步方式执行
尽量不使用void作为返回类型,若希望异步方法返回void类型,请使用Task
异步方法名称以Async结尾
异步方法中不能声明使用ref或out关键字修饰的变量
使用async await
private async void button45_ClickAsync(object sender, EventArgs e)
{//如果使用await 那么方法要加async关键字 这里不需要返回结果把方法改为void的即可 不然报错
//会先执行方法三 因为方法三使用了await(等待) 这里会等待方法三执行完后再去执行其它方法
//方法一是普通异步方法但是耗时较长,在执行的过程中返回了 所以方法二会优于方法一执行
await 方法三Async();
方法一();
方法二();
}
public void 方法二() {
Console.WriteLine("同步方法2");
}
public async Task 方法三Async()
{//如果使用await 那么方法要加async关键字
Console.WriteLine("1111");
await Task.Run(() =>
{//在这里我们使用了await 会等待task.run的内容结束后再去执行输出22222
Thread.Sleep(4000);
Console.WriteLine("同步方法3");
});
Console.WriteLine("22222");
}
public void 方法一() {
Task.Run(() =>
{
Thread.Sleep(3000);
Console.WriteLine("异步方法1");
});
}
让两个异步函数同时运行,执行完后再跑剩下的方法
我们在代码中可能会遇到异步函数执行过快但是还没有得到结果就报错了,这里我们使用whenAll可以解决
private async void button48_Click(object sender, EventArgs e)
{
Console.WriteLine("1111");
await Task.WhenAll(func1(), func2());
Console.WriteLine("4444");
}
private static async Task func1()
{
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("2222");
});
}
private static async Task func2()
{
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("3333");
});
}