麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

await之后的線程問題

2019-11-17 02:56:27
字體:
供稿:網(wǎng)友

await之后的線程問題

之前看了園子里的一篇文章「async & await的前世今生」,收益頗多。而其中有句話被博主特意用紅色標(biāo)注,所以留意多看了幾眼,「await 之后不會開啟新的線程(await 從來不會開啟新的線程)」。在MSDN上找到的相關(guān)資料也佐證了其正確性——The async and await keyWords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.(async 和 await 關(guān)鍵字不會導(dǎo)致創(chuàng)建其他線程。 因為異步方法不會在其自身線程上運行,因此它不需要多線程。 只有當(dāng)方法處于活動狀態(tài)時,該方法將在當(dāng)前同步上下文中運行并使用線程上的時間。)

再建立一個Windows Forms應(yīng)用工程,寫點代碼更形象地說明問題:

PRivate void Form1_Load(object sender, EventArgs e){    PrintDataAsync();    Debug.Print("three");}private async void PrintDataAsync(){    Task<int> result = CalculateDataAsync();    Debug.Print("second");    int data = await result;    Debug.Print("last:" + data);}private async Task<int> CalculateDataAsync(){    Debug.Print(string.Format("{0} : {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));    Debug.Print("first");    int result = 0;    for (int i = 0; i < 10; i++)    {        result += i;    }    await Task.Delay(1000);    Debug.Print("four");    Debug.Print(string.Format("{0} : {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));    return result;};

程序的結(jié)果如預(yù)期的一樣,Output窗口中可以看到以下內(nèi)容:

8 : Falsefirstsecondthreefour8 : Falselast:45

await之前的ManagedThreadId值與之后的ManagedThreadId值一致,IsThreadPoolThread始終是False,說明當(dāng)前線程沒有發(fā)生改變,也沒有產(chǎn)生新的線程。

但如果建立的是Console應(yīng)用工程,結(jié)果就不同了。

static void Main(string[] args){    PrintDataAsync();    Console.WriteLine("three");    Console.Read();}private static async void PrintDataAsync(){    Task<int> result = CalculateDataAsync();    Console.WriteLine("second");    int data = await result;    Console.WriteLine("last:" + data);}private static async Task<int> CalculateDataAsync(){    Console.WriteLine(string.Format("{0} : {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));    Console.WriteLine("first");    int result = 0;    for (int i = 0; i < 10; i++)    {        result += i;    }    await Task.Delay(1000);    Console.WriteLine("four");    Console.WriteLine(string.Format("{0} : {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));    return result;}

這段代碼的執(zhí)行結(jié)果:

8 : Falsefirstsecondthreefour10 : Truelast:45

ManagedThreadId在await之后發(fā)生了變化,IsThreadPoolThread也變?yōu)榱薚rue,說明不是同一個線程。

為什么會這樣?再看一下MSDN中描述——「The method runs on the current synchronization context and uses time on the thread only when the method is active」,這里涉及到SynchronizationContext對象的使用。

在Windows Forms工程代碼中加入Debug.Print(SynchronizationContext.Current.ToString()); 檢測代碼,其輸出是System.Windows.Forms.WindowsFormsSynchronizationContext。

而如果在Console工程中加入類似的檢測代碼Console.WriteLine(SynchronizationContext.Current.ToString()); 則會拋出空引用異常,因為SynchronizationContext.Current在Console工程中的值為null。

又從MSDN Magazine找到SynchronizationContext相關(guān)的文章,其中有介紹到:By convention, if a thread’s current SynchronizationContext is null, then it implicitly has a default SynchronizationContext.(根據(jù)慣例,如果一個線程的當(dāng)前 SynchronizationContext 為 null,那么它隱式具有一個默認(rèn) SynchronizationContext。)The default SynchronizationContext is applied to ThreadPool threads unless the code is hosted by asp.net.(默認(rèn) SynchronizationContext 應(yīng)用于 ThreadPool 線程,除非代碼由 ASP.NET 承載。)

這里提到了APS.NET,所以再建個Web Forms應(yīng)用工程用于驗證:

protected void Page_Load(object sender, EventArgs e){    PrintDataAsync();    Debug.Print("three");}private async void PrintDataAsync(){    Debug.Print(SynchronizationContext.Current.ToString());    Task<int> result = CalculateDataAsync();    Debug.Print("second");    int data = await result;    Debug.Print("last:" + data);}private async Task<int> CalculateDataAsync(){    Debug.Print(string.Format("{0} : {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));    Debug.Print("first");    int result = 0;    for (int i = 0; i < 10; i++)    {        result += i;    }    await Task.Delay(1000);    Debug.Print("four");    Debug.Print(string.Format("{0} : {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));    return result;}

輸出結(jié)果:

System.Web.AspNetSynchronizationContext8 : Truefirstsecondthreefour9 : Truelast:45

ManagedThreadId值發(fā)生改變,IsThreadPoolThread始終是True,SynchronizationContext.Current值為System.Web.AspNetSynchronizationContext。

由三次試驗及相關(guān)資料可以得出結(jié)論,await之后的線程依據(jù)SynchronizationContext在不同環(huán)境中的不同定義而產(chǎn)生不同的結(jié)果。所以「await 之后不會開啟新的線程(await 從來不會開啟新的線程)」的肯定句式改成「await 之后會開啟新的線程嗎? Maybe」這樣的句式更加合適些。

最后補充一點,若是把第一個Windows Forms工程的代碼await Task.Delay(1000);改成await Task.Delay(1000).ConfigureAwait(false); 的話,則可以得到第二個Console工程同樣的結(jié)果。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 一级α片 | 国产精品视频自拍 | 免费观看一级淫片 | 免费一级毛片在线播放不收费 | 午夜激情视频免费 | chinese 军人 gay xx 呻吟 | 久久国产在线观看 | 999久久国精品免费观看网站 | 欧美成视频在线观看 | 久久久久久久久久久av | 欧美日本日韩 | 日本在线不卡一区二区三区 | 日本不卡一区二区在线观看 | 黑人三级毛片 | 日韩黄色一级视频 | 国产成人高清在线观看 | 亚洲射逼 | 精品国产视频一区二区三区 | 欧美成人小视频 | 九九热精品视频在线播放 | 毛片免费视频 | 男女羞羞在线观看 | 中文字幕视频在线播放 | 精品久久久久久久 | 欧美精品一区二区三区四区 | 免费视频一区 | 国产交换3p国产精品 | 黄 色 免费网 站 成 人 | 91精品国产综合久久男男 | 黄色片网站免费在线观看 | 九九热在线视频免费观看 | av懂色| 黄色片视频观看 | 免费专区 - 91爱爱 | 亚洲一级电影在线观看 | 可以看逼的视频 | 日韩欧美激情视频 | 一级免费在线视频 | 成品片a免人视频 | 成av在线| 欧美国产一区二区三区 |