15.3 Task Task.Yield和Task.Delay说明
Posted kikyoqiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了15.3 Task Task.Yield和Task.Delay说明相关的知识,希望对你有一定的参考价值。
https://blog.csdn.net/hurrycxd/article/details/79827958
书上看到一个Task.Yield例子,Task.Yield方法创建一个立即返回的awaitable。等待一个Yield可以让异步方法在执行后续的部分时返回到调用方法。可以理解为离开当前的消息队列,回到队列末尾,让处理器有时间处理其他任务。
Yield方法在GUI编程中非常的有用,可以中断大量的工作,让其他任务使用处理器。看下面的代码:
1 static void Main(string[] args) 2 { 3 Task<int> value = FindSeriesSum(100000); 4 Console.WriteLine("主线其他任务开始"); 5 CountBig(10000); 6 CountBig(10001); 7 CountBig(10002); 8 Thread.Sleep(1000); 9 CountBig(10003); 10 Console.WriteLine("Length =" + value.Result); 11 Console.ReadKey(); 12 } 13 public static async Task<int> FindSeriesSum(int i1) 14 { 15 int sum = 0; 16 for (int i = 0; i < i1; i++) 17 { 18 sum += i1; 19 if (i % 20000 == 0) 20 { 21 await Task.Yield(); 22 Console.WriteLine("i % 20000 :i=" + i); 23 } 24 } 25 WebClient wc = new WebClient(); 26 Console.WriteLine("开始下载任务"); 27 string str = await wc.DownloadStringTaskAsync("https://www.baidu.com"); 28 return str.Length; 29 } 30 private static void CountBig(int p) 31 { 32 for (int i = 0; i < p; i++) 33 { 34 if (i == p - 1) 35 Console.WriteLine("p =" + p); 36 } 37 }
在执行下载任务await wc.DownloadStringTaskAsync("https://github.com/")前进行了大量的CPU运算,那么线程会等到第一个await的时候才会异步执行CountBig(10000);
程序运行的结果如下:
i % 20000 :i=0
i % 20000 :i=20000
i % 20000 :i=40000
i % 20000 :i=60000
i % 20000 :i=80000
开始下载任务
主线其他任务开始
p =10000
p =10001
p =10002
p =10003
Length =52728
我们需要立即返回的awaitable,让程序执行其他的任务,去掉//await Task.Yield();前面的注释符,得到的结果如下:
i % 20000 :i=0
主线其他任务开始
p =10000
i % 20000 :i=20000
p =10001
p =10002
i % 20000 :i=40000
i % 20000 :i=60000
i % 20000 :i=80000
开始下载任务
p =10003
Length =52728
可以看到现在开始下载任务之前就可以执行其他的任务了。最大条件的利用了资源。
Task.Delay方法创建一个Task对象,该对象暂停其在线程中的处理。
与Thread.Sleep()阻塞线程不同的是,Task.Delay不会阻塞线程,线程可以继续处理其它的工作。
1 static void Main(string[] args) 2 { 3 Task<int> value = FindSeriesSum(100000); 4 Console.WriteLine("主线其他任务开始"); 5 CountBig(10000); 6 CountBig(10001); 7 CountBig(10002); 8 Thread.Sleep(1000); 9 CountBig(10003); 10 Console.WriteLine("Length =" + value.Result); 11 Console.ReadKey(); 12 } 13 public static async Task<int> FindSeriesSum(int i1) 14 { 15 await Task.Delay(1000); 16 WebClient wc = new WebClient(); 17 Console.WriteLine("开始下载任务"); 18 string str = await wc.DownloadStringTaskAsync("https://www.baidu.com"); 19 return str.Length; 20 } 21 private static void CountBig(int p) 22 { 23 for (int i = 0; i < p; i++) 24 { 25 if (i == p - 1) 26 Console.WriteLine("p =" + p); 27 } 28 }
主线其他任务开始
p =10000
p =10001
p =10002
开始下载任务
p =10003
Length =52728
以上是关于15.3 Task Task.Yield和Task.Delay说明的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Thread.CurrentPrincipal 需要“等待 Task.Yield()”才能正确流动?
在实现生产者/消费者模式时使用 Task.Yield 克服 ThreadPool 饥饿
在用户界面和控制台应用程序中使用 Task.Yield() 的区别