亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#中怎么使用Task.Yeild()函數

發布時間:2020-07-15 15:35:05 來源:億速云 閱讀:215 作者:小豬 欄目:開發技術

這篇文章主要講解了C#中怎么使用Task.Yeild()函數,內容清晰明了,相信大家閱讀完之后會有幫助。

      在與同事討論async/await內部實現的時候,突然想到Task.Yeild()這個函數,為什么呢,了解一點C#async/await內部機制的都知道,在await一個異步任務(函數)的時候,它會先判斷該Task是否已經完成,如果已經完成,則繼續執行下去,不會返回到調用方,原因是盡量避免線程切換,因為await后面部分的代碼很可能是另一個不同的線程執行,而Task.Yeild()則可以強制回到調用方,或者說主動讓出執行權,給其他Task執行的機會,可以把Task理解為協程,Task.Yeild()和Thread.sleep(0)有點相同。

      為了證明我的結論成立,請看代碼:

public static async Task Test1()
{
   await Task.CompletedTask;
   Thread.Sleep(1000);
   Console.WriteLine("Test1任務完成");
}
public static async Task Test2()
{
   await Task.Delay(1);
   Thread.Sleep(1000);
   Console.WriteLine("Test2任務完成");
}
public static async Task Test3()
{
   await Task.Yield();
   Thread.Sleep(1000);
   Console.WriteLine("Test3任務完成");
}
static void Main(string[] args)
{
   Console.WriteLine(DateTime.Now);
   _ = Test1();
   Console.WriteLine(DateTime.Now);
   Console.ReadLine();
}

      按照開頭的理論,Test1()異步函數由于await了一個已經完成的任務,所以會繼續往下執行,阻塞1秒鐘,然后回到調用方,打印的時間之差會相隔一秒。

C#中怎么使用Task.Yeild()函數

      Test2()異步函數由于await了一個未完成的任務(1ms對于CPU來說是很長的了),所以會返回調用方,然后打印相同的時間,一秒鐘之后會打印執行完畢。

C#中怎么使用Task.Yeild()函數

      Test3()調用了Task.Yeild()函數,主動讓出執行權,所以會直接返回調用方,然后打印相同的時間,一秒之后會打印執行完畢。

C#中怎么使用Task.Yeild()函數

      可以看到,開頭的結論是正確的。那么,有什么意義呢?Yeild的意思在這里其實就是退讓,讓出的意思,讓出什么呢?就是讓出執行權,這與Thread.sleep(0)讓出CPU執行權給其他線程(前提是有其他線程競爭)有機會執行是一個道理。

      請看我的例子:

public static async Task OP1()
{
   while (true)
   {
     await Task.Yield();//這里會捕捉同步上下文,由于是控制臺程序,沒有同步上下文,所以默認的線程池任務調度器變成同步上下文
                   //也就是說后面的代碼將會在線程池上執行,由于線程池工作線程數量設置為1,所以必須主動讓出執行權,讓其他的
                   //任務有執行的機會
     Console.WriteLine("OP1在執行");
     Thread.Sleep(1000);//模擬一些需要占用CPU的操作
   }
}
public static async Task OP2()
{
   while (true)
   {
     await Task.Yield();
     Console.WriteLine("OP2在執行");
     Thread.Sleep(1000);
   }
}
static async Task Main(string[] args)
{
   ThreadPool.SetMinThreads(1, 1);
   ThreadPool.SetMaxThreads(1, 1);
   //Task.Run()方法默認使用線程池任務調度器執行任務,由于主線程不是線程池線程,所以使用Task.Run()
   var t = Task.Run(async () =>
   {
     var t1 = OP1();
     var t2 = OP2();
     await Task.WhenAll(t1, t2);
   });
   await t;
   Console.ReadLine();
}

C#中怎么使用Task.Yeild()函數

      可以看出OP1()和OP2()兩個協程(Task)互相爭用一個線程(用戶模式下的CPU),如果不主動讓出執行權,另一個協程(Task)將不會有機會執行。

      例如:

public static async Task OP2()
{
   while (true)
   {
     await Task.CompletedTask;//或者是直接去掉
     Console.WriteLine($"OP2在執行 {DateTime.Now}");
     Thread.Sleep(1000);
   }
}

      這樣OP1()將永遠不會有機會執行。

C#中怎么使用Task.Yeild()函數

看完上述內容,有沒有對C#中怎么使用Task.Yeild()函數有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东源县| 周宁县| 星子县| 巢湖市| 宿松县| 松阳县| 沽源县| 惠水县| 菏泽市| 安新县| 堆龙德庆县| 博爱县| 伊春市| 仁寿县| 南汇区| 十堰市| 榆中县| 镇平县| 独山县| 延安市| 大连市| 淄博市| 乡城县| 兰州市| 沙河市| 秦皇岛市| 马龙县| 合阳县| 西吉县| 平泉县| 呼和浩特市| 荥阳市| 蒙城县| 涿州市| 库车县| 西华县| 望江县| 易门县| 桐庐县| 昭觉县| 汶川县|