一、不要用sleep()
如果想在异步方法中暂停一段时间,不要用Thread.sleep(),因为它会阻塞调用线程,而要用await.Task.Delay()。
举例:
 下载一个网址,3秒后下载另一个
示例:
sleep()
为了能直观看到效果,使用winform项目

 
 此时点击按钮之后,页面便卡死不动了,不能在进行操作。因为Sleep()方法,阻塞了主线程。
 睡眠结束后,才能继续操纵界面
注释后,便能在下载过程中,继续操作页面
 
await task.delay()
不会阻塞主线程

 此时界面也是可正常操作
在控制台中没看到区别,但是放到WinForm程序中就能看到区别了ASP.NET Core中也看不到区别但是sleep()会降低并发
二、CancellationToken
概念:
多线程一般用于处理比较耗时的操作,
 有时需要提前终止任务,比如:
 请求超时、用户取消请求。很多异步方法都有
 CancellationToken参数,用于获得提前终止执行的信号。
 (下载文件暂停,用户关闭网页请求终止)
方法:
CancellationToken结构体
 None:空
 ()bool lsCancellationRequested是否取消(用于判断请求者,是否终止请求)
 Register(Action callback)注册取消监听
 ()Throw lfcancellationRequested()如果任务被取消,执行到这句话就抛异常
CancellationTokenSource
 CancelAfter()超时后发出取消信号
 Cancel()发出取消信号
 CancellationToken Token
示例:
为“下载一个网址N次”的方法增加取消功能。
 分别用GetstringAsync+IsCancellationRequested、GetStringAsync+ThrowlfCancellatiorRequested()、带CancellationToken的GetAsync()分别实现:取消分别用超时、用户敲按键(不能await)实现。
1.普通方式

运行结果:
 
 下载一百遍终止。
2.加入cancellationtoken

 调用
 
调用结果:
 请求被取消

3.cancellationToken.ThrowIfCancellationRequested()

运行结果,会抛出异常
 
4.调用封装好的getAsync()方法

 
 运行结果
 抛出异常

cancel() 手动取消

ASP.NET Core开发中,一般不需要自已处理CancellationToken.
 CancellationTokenSource这些,只要做到“能转发CancellationToken就转发即可。ASP.NET Core会对于用户请求中断进行处理。
 (*)演示一下ASP.NETCore中的使用:写一个方法,Delay1000次,用Debug.WriteLine()输出,访问中间跳到放到其他网站。

 访问其他网站的时候,就会抛出异常,暂停下载
 
三、WhenAll()
Task类的重要方法:
- Task WhenAny(lEnumerabletasks)等,任何一个Task完成,Task就完成
- Task<TResult[]> WhenAll(paramsTask[]tasks)等,所有Task完成,Task才完成。用于等待多个任务执行结束,但是不在乎它们的执行顺序。
- FromResult()创建普通数值的Task对象。
示例
Task tl =File.ReadAllTextAsync(“d:/l.txt”);
 Task t2 =File.ReadAllTextAsync(“d:/2.txt”);
 Task t3 =File.ReadAllTextAsync(“d:/3.txt”);
 string[] results = await Task.WhenAll(t1, t2, t3)
 string s1 = results[0];
 string s2 = results[1];
 string s3 = results[2];
1.whenall

运行结果
 
案例:
计算一个文件夹下,所有文本文件的单词个数汇总。
 
 运行结果
 
四、异步其他问题
接口中的异步方法:
async是提示编译器为异步方法中的await代码进行分段处理的,而一个异步方法是否修饰了async对于方法的调用者来讲没区别的,因此对于接口中的方法或者抽象方法不能修饰为async。

 在实现类中添加async

异步与yield:
复习: yield return不仅能够简化数据的返回,而且可以让数据处理“流水线化”,提升性能。
static lEnumerable<string> Test()
{
	yield return "hello",
	yield return "'yzk" ;
	yield return "'youzack";
}

 运行结果
 
 在旧版C#中,async方法中不能用yield。
 从C#8.0开始,把返回值声明为IAsyncEnumerable(不要带Task),然后遍历的时候用await foreach()即可。
static async Task Main(string[] args)
{
	await foreach(var s in Test())
	Console.WriteLine(s);
}
static async lAsyncEnumerable<string> Test()
{
	yield return "hello";
	yield return "yzk";
	yield return "youzack";
}










