一、基本概念
在C#中,async和await关键字用于异步编程。异步编程允许程序在执行I/O密集型操作时不会被阻塞,从而提高程序的性能和响应性。
async关键字用于定义异步方法,表明该方法可能包含await表达式,并且可以在其执行期间异步等待其他操作的完成。
await关键字用于等待异步操作完成,它只能在async方法内使用。await表达式会挂起当前方法的执行,直到其等待的操作完成,然后恢复方法的执行。
二、使用方法调用的方式
代码如下(示例):
using System;
using System.Collections.Generic;
using System.Threading.Tasks;class Program
{static void Main(string[] args){// 调用 test 方法,该方法是异步的,但不会阻塞主线程test();Console.WriteLine("main end..."); // 输出主函数结束的提示Console.ReadKey(); // 等待用户输入任意键,保持程序运行}// 异步方法 teststatic async void test(){// 异步等待 2000 毫秒(2 秒)await Task.Delay(2000);// 调用 stest 方法创建三个异步任务Task<int> Result0 = stest(100, 2000);Task<int> Result1 = stest(200, 3000);Task<int> Result2 = stest(300, 4000);// 创建一个任务列表,将三个异步任务添加到列表中List<Task<int>> tsklst = new List<Task<int>>();tsklst.AddRange(new List<Task<int>> { Result0, Result1, Result2 });// 输出开始执行异步任务的提示Console.WriteLine("delegateFuncTaskReturn has been Started {0}", 100);// 使用 Task.WhenAny 方法异步等待任务列表中的任意一个任务完成Task<int> firstCompletedTask = await Task.WhenAny(tsklst);// 输出异步任务完成后的提示Console.WriteLine("after WhenAny");Console.WriteLine("firstCompletedTask has been done and returned value {0}", firstCompletedTask.Result);Console.WriteLine("program end"); // 输出程序结束的提示}// 异步方法 stest,接受一个整数参数 input 和一个整数参数 delaystatic async Task<int> stest(int input, int delay){// 异步等待指定的延迟时间await Task.Delay(delay);// 输出异步方法执行完成的提示,并打印输入值加 1 的结果Console.WriteLine("delegateFuncTaskReturn has been done and returned value {0}", input + 1);// 再次异步等待 1000 毫秒(1 秒)await Task.Delay(1000);// 返回输入值减去 1return input - 1;}
}
这段代码的主要逻辑是创建了三个异步任务(Result0
、Result1
、Result2
),每个任务都会在一定的延迟后返回一个结果。然后,使用 Task.WhenAny
方法等待任意一个任务完成。在 test
方法中,还输出了一些提示信息以表示异步任务的启动和完成状态。
以下是代码的执行过程和输出结果的总结:
- 主函数
Main
开始执行,调用test
方法。 test
方法异步等待了 2000 毫秒(2 秒)。stest
方法被调用三次,每次传入不同的参数,并且每个方法内部会异步等待一定的延迟时间后返回结果。- 输出了五次 “delegateFuncTaskReturn has been Started 100” 的提示信息,表示异步任务已经启动。
- 使用
Task.WhenAny
方法等待任意一个任务完成。 - 当第一个任务完成时,输出了 “after WhenAny” 的提示信息,并打印了第一个完成任务的结果。
- 最后输出 “program end” 表示程序执行结束。
因为 Task.WhenAny
方法会返回第一个完成的任务,所以输出结果可能会因为任务执行顺序不同而有所不同,但总体上,程序会在异步任务完成后输出相应的提示信息和结果。输出结果如下:
test start...
main end...
delegateFuncTaskReturn has been Started 100
delegateFuncTaskReturn has been done and returned value 101
after WhenAny
firstCompletedTask has been done and returned value 99
program end
delegateFuncTaskReturn has been done and returned value 201
delegateFuncTaskReturn has been done and returned value 301
三、使用lamda和异步委托的方式
代码如下(示例):
using System;
using System.Collections.Generic;
using System.Threading.Tasks;class Program
{static void Main(string[] args){Console.WriteLine("test2 start..."); // 输出测试开始的提示信息test2(); // 调用异步方法 test2Console.WriteLine("main end..."); // 输出主函数结束的提示信息Console.ReadKey(); // 等待用户输入任意键,保持程序运行}// 异步方法 test2static async void test2(){await Task.Delay(2000); // 异步等待 2000 毫秒(2 秒)// 使用 lambda 表达式定义异步委托 stestFunc<int, int, Task<int>> stest = async (int input, int delay) =>{await Task.Delay(delay); // 异步等待指定的延迟时间Console.WriteLine("delegateFuncTaskReturn has been done and returned value {0}", input + 1); // 输出异步方法执行完成的提示,并打印输入值加 1 的结果await Task.Delay(1000); // 再次异步等待 1000 毫秒(1 秒)return input - 1; // 返回输入值减去 1};// 创建三个异步任务,每个任务传入不同的参数Task<int> Result0 = stest(100, 2000);Task<int> Result1 = stest(200, 3000);Task<int> Result2 = stest(300, 4000);List<Task<int>> tsklst = new List<Task<int>>(); // 创建任务列表tsklst.AddRange(new List<Task<int>> { Result0, Result1, Result2 }); // 将三个异步任务添加到列表中Console.WriteLine("delegateFuncTaskReturn has been Started {0}", 100); // 输出异步任务已经启动的提示信息// 使用 Task.WhenAny 方法异步等待任务列表中的任意一个任务完成Task<int> firstCompletedTask = await Task.WhenAny(tsklst);Console.WriteLine("after WhenAny"); // 输出异步任务完成后的提示信息Console.WriteLine("firstCompletedTask has been done and returned value {0}", firstCompletedTask.Result); // 打印第一个完成任务的结果Console.WriteLine("program end"); // 输出程序结束的提示信息}
}
这段代码与之前的代码类似,不同之处在于 test2
方法中使用了 lambda 表达式来定义异步委托 stest
,而不是单独定义一个异步方法 stest
。
以下是代码的执行过程和解释:
- 主函数
Main
开始执行,调用test2
方法。 test2
方法异步等待了 2000 毫秒(2 秒)。- 使用 lambda 表达式定义了一个异步委托
stest
,该委托接受两个参数input
和delay
,并在内部异步等待一定的延迟时间后返回一个结果。 - 使用
stest
异步委托创建了三个异步任务Result0
、Result1
和Result2
,每个任务传入不同的参数。 - 输出了五次 “delegateFuncTaskReturn has been Started 100” 的提示信息,表示异步任务已经启动。
- 使用
Task.WhenAny
方法等待任意一个任务完成。 - 当第一个任务完成时,输出了 “after WhenAny” 的提示信息,并打印了第一个完成任务的结果。
- 最后输出 “program end” 表示程序执行结束。
与之前的代码相比,这段代码的主要区别在于使用了 lambda 表达式来定义异步委托,使代码更加简洁和紧凑。代码主要利用了异步方法和异步委托来实现并行执行多个任务。主要执行步骤和注释已经在代码中说明。
test2 start...
main end...
delegateFuncTaskReturn has been Started 100
delegateFuncTaskReturn has been done and returned value 101
after WhenAny
firstCompletedTask has been done and returned value 99
program end
delegateFuncTaskReturn has been done and returned value 201
delegateFuncTaskReturn has been done and returned value 301
四、稍加修改变成阻塞方法
代码如下(示例):
using System;
using System.Collections.Generic;
using System.Threading.Tasks;class Program
{static async Task Main(string[] args){Console.WriteLine("test2 start..."); // 输出测试开始的提示信息await test2(); // 异步调用 test2 方法,并等待其完成Console.WriteLine("main end..."); // 输出主函数结束的提示信息Console.ReadKey(); // 等待用户输入任意键,保持程序运行}// 异步方法 test2,返回一个 Task<int> 对象static async Task<int> test2(){await Task.Delay(2000); // 异步等待 2000 毫秒(2 秒)// 使用 lambda 表达式定义异步委托 stestFunc<int, int, Task<int>> stest = async (int input, int delay) =>{await Task.Delay(delay); // 异步等待指定的延迟时间Console.WriteLine("delegateFuncTaskReturn has been done and returned value {0}", input + 1); // 输出异步方法执行完成的提示,并打印输入值加 1 的结果await Task.Delay(1000); // 再次异步等待 1000 毫秒(1 秒)return input - 1; // 返回输入值减去 1};// 创建三个异步任务,每个任务传入不同的参数Task<int> Result0 = stest(100, 2000);Task<int> Result1 = stest(200, 3000);Task<int> Result2 = stest(300, 4000);List<Task<int>> tsklst = new List<Task<int>>(); // 创建任务列表tsklst.AddRange(new List<Task<int>> { Result0, Result1, Result2 }); // 将三个异步任务添加到列表中Console.WriteLine("delegateFuncTaskReturn has been Started"); // 输出异步任务已经启动的提示信息// 使用 Task.WhenAny 方法异步等待任务列表中的任意一个任务完成Task<int> firstCompletedTask = await Task.WhenAny(tsklst);Console.WriteLine("after WhenAny"); // 输出异步任务完成后的提示信息Console.WriteLine("firstCompletedTask has been done and returned value {0}", firstCompletedTask.Result); // 打印第一个完成任务的结果Console.WriteLine("program end"); // 输出程序结束的提示信息return 0; // 返回 0,表示方法执行完成}
}
这段代码利用了异步方法和异步委托来实现并行执行多个任务,并且在 Main 方法中也使用了异步特性。主要执行步骤和注释已经在代码中说明。增加await关键字使它变成阻塞的方法。
输出结果如下:
test2 start...
delegateFuncTaskReturn has been Started
delegateFuncTaskReturn has been done and returned value 101
after WhenAny
firstCompletedTask has been done and returned value 99
program end
main end...
delegateFuncTaskReturn has been done and returned value 201
delegateFuncTaskReturn has been done and returned value 301