.NET异步和多线程系列(六)- async/await
proginn468312
共 5298字,需浏览 11分钟
·
2020-09-12 19:50
本文是.NET异步和多线程系列的第六章,本章主要对之前介绍过的async/await做一些补充说明。
下面我们直接来看下代码和运行结果:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace MyAsyncAwait
{
///
/// await/async 是C#保留关键字,通常是成对出现,语法糖。
///
/// 主线程调用async/await方法,主线程遇到await返回执行后续动作,
/// await后面的代码会等着Task任务的完成后再继续执行
/// 其实就像把await后面的代码包装成一个ContinueWith的回调动作
/// 然后这个回调动作可能是Task线程,也可能是新的子线程,也可能是主线程
///
/// 一个async方法,如果没有返回值,可以方法声明返回Task
/// await/async能够用同步的方式编写代码,但又是非阻塞的。
///
/// async方法在编译后会生成一个状态机(实现了IAsyncStateMachine接口)
///
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"当前主线程开始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
AwaitAsyncClass.TestShow();
Console.WriteLine($"当前主线程结束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Console.ReadKey();
}
}
///
/// await/async关键字 语法糖
/// await/async 要么不用 要么用到底
///
public class AwaitAsyncClass
{
public static void TestShow()
{
Test();
}
private async static Task Test()
{
Console.WriteLine($"Test开始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Task<long> t = SumAsync();
Console.WriteLine($"遇到await主线程回来干活了 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
{
long lResult = await t; //await后面的代码会由线程池的线程执行,非阻塞。
Console.WriteLine($"最终得到的lResult={lResult}");
}
{
//t.Wait(); //主线程等待Task的完成,阻塞的
//long lResult = t.Result; //访问Result,主线程等待Task的完成,阻塞的,效果跟t.Wait()一样
//Console.WriteLine($"最终得到的lResult={lResult}");
}
Console.WriteLine($"Test结束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
}
///
/// 带返回值的Task
/// 要使用返回值就一定要等子线程计算完毕
///
private static async Task<long> SumAsync()
{
Console.WriteLine($"SumAsync start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long result = 0;
//await后面的代码会等着Task任务的完成后再继续执行
//其实就像把await后面的代码包装成一个ContinueWith的回调动作
//然后这个回调动作可能是Task线程,也可能是新的子线程,也可能是主线程
await Task.Run(() =>
{
for (int k = 0; k < 2; k++)
{
Console.WriteLine($"SumAsync 第1个 await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
}
for (long i = 0; i < 999_999_999; i++)
{
result += i;
}
});
Console.WriteLine($"SumAsync 第1个 await Task.Run的后续任务开始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
await Task.Run(() =>
{
for (int k = 0; k < 2; k++)
{
Console.WriteLine($"SumAsync 第2个 await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
}
for (long i = 0; i < 999_999_999; i++)
{
result += i;
}
});
Console.WriteLine($"SumAsync 第2个 await Task.Run的后续任务开始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
await Task.Run(() =>
{
for (int k = 0; k < 2; k++)
{
Console.WriteLine($"SumAsync 第3个 await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
}
for (long i = 0; i < 999_999_999; i++)
{
result += i;
}
});
Console.WriteLine($"SumAsync end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
return result;
}
}
}
运行结果如下:
仔细观察结果会发现:
主线程调用async/await方法,主线程遇到await后会返回执行后续动作;
await后面的代码会等着Task任务的完成后再继续执行,其实就像把await后面的代码包装成一个ContinueWith的回调动作;
然后这个回调动作可能是Task线程,也可能是新的子线程,也可能是主线程;
await/async能够用同步的方式编写代码,但又是非阻塞的。
下面我们调整下Test方法后再运行(红色的为调整部分):
private async static Task Test()
{
Console.WriteLine($"Test开始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Task<long> t = SumAsync();
Console.WriteLine($"遇到await主线程回来干活了 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
{
//long lResult = await t; //await后面的代码会由线程池的线程执行,非阻塞。
//Console.WriteLine($"最终得到的lResult={lResult}");
}
{
//t.Wait(); //主线程等待Task的完成,阻塞的
long lResult = t.Result; //访问Result,主线程等待Task的完成,阻塞的,效果跟t.Wait()一样
Console.WriteLine($"最终得到的lResult={lResult}");
}
Console.WriteLine($"Test结束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
}
调整后运行结果如下:
仔细观察结果会发现:
访问Result,主线程会等待Task的完成,阻塞的。
其实async方法在编译后会生成一个状态机(实现了IAsyncStateMachine接口),有兴趣的可以自行去了解下。
至此本文就介绍完了,有兴趣的还可以看下我之前写过一篇也是关于async/await的文章:https://www.cnblogs.com/xyh9039/p/11391507.html
Demo源码:
链接:https://pan.baidu.com/s/1jnG5IpteuKCdmF6-tr--cA
提取码:3onm
此文由博主精心撰写转载请保留此原文链接:https://www.cnblogs.com/xyh9039/p/13622122.html
版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!
版权申明:本文来源于网友收集或网友提供,如果有侵权,请转告版主或者留言,本公众号立即删除。
评论