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() 的区别

await Task.Yield(); 超简单理解!

5min+帮我排个队,谢谢。await Task.Yield()

15.3 Task 异常