C#异步多线程——async/await异步方法

C#实现异步多线程的方式有多种,以下总结的是async/await异步方法。

环境准备

基于.NET6创建控制台项目进行测试,下面提前准备几个方法,防止后续举例时代码重复。

//封装一个打印调试方法,输出线程ID和时间戳
private static void LogDebug(string msg)
{
   
   
    Console.WriteLine($"{
     
     msg} 【ThreadId {
     
     Thread.CurrentThread.ManagedThreadId.ToString("00")}{
     
     DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
}
//封装一个方法模拟一个长时间的计算
private static long DoSomethingLong()
{
   
   
    long lResult = 0;
    for (int i = 0; i < 500000000; i++)
    {
   
   
        lResult += i;
    }
    return lResult;
}
//封装一个方法产生一个很大的字符串用于模拟耗时的写入文件操作
private static string GenBigString()
{
   
   
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < 1000000; i++)
    {
   
   
        stringBuilder.Append("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
    }
    return stringBuilder.ToString();
}

编写异步方法

  • async用于修饰方法声明,await出现在Task对象或泛型Task<T>对象前面。
  • async/await 通常是成对出现的,只有async没有await没什么意义,执行结果和不加async的普通方法没有区别;有await调用,则这个方法必须修饰为async,否则会报错。
  • 异步方法名字一般以Async结尾。

无返回值

  • 没有返回值的情况,最好把返回值声明为非泛型的Task而不是void,方法体我们仍按照无返回值去编写,无需手动return一个Task对象。
private static async Task NoReturnAsync(string srcFile, string destFile)
{
   
   
    string context = await File.ReadAllTextAsync(srcFile);
    await File.WriteAllTextAsync(destFile, context);
}

static async Task Main(string[] args)
{
   
   
    LogDebug("Project start");

    await NoReturnAsync(@"E:\temp\LambdaAsync.txt", @"E:\temp\LambdaAsync.cp.txt");
    LogDebug("Copy complete");

    Console.Read();
}

有返回值

  • 有返回值的异步方法,返回值为 Task<T>,T是真正的返回类型。
  • 调用异步方法时,在 Task<T> 对象前面加上await关键字,这样拿到的结果就是泛型指定的T类型。
  • 在使用return返回结果时,我们只要返回泛型 Task<T>指定的T类型即可。
private static async Task<bool> WithReturnAsync(string srcFile, string destFile)
{
   
   
    bool result = false;
    //读取源文件
    string srcFileContext = await File.ReadAllTextAsync(srcFile);
    int srcFileLength = srcFileContext.Length;

	//读取内容写入目标文件
    await File.WriteAllTextAsync(destFile, srcFileContext);

	//读取目标文件
    string destFileContext = await File.ReadAllTextAsync(destFile);
    int destFileLength = destFileContext.Length;

	//比较源文件和目标文件长度是否相同
    if (destFileLength == srcFileLength)
        result = true;

    return result;
}

static async Task Main(string[] args)
{
   
   
    LogDebug("Project start");

    bool result = await WithReturnAsync(@"E:\temp\LambdaAsync.txt", @"E:\temp\LambdaAsync.cp.txt");
    if (result)
        LogDebug("文件拷贝成功");
    else
        LogDebug("文件拷贝失败");

    Console.Read();
}

异步委托

如果在lambda表达式中需要调用异步方法,可以用async把这个lambda修饰为异步,否则会报错(The ‘await’ operator can only be used within an async lambda expression. Consider marking this lambda expression with the ‘async’ modifier.)。

private static Task LambdaAsync(string fileName, string str)
{
   
   
    return Task.Run(async () => await File.WriteAllTextAsync(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值