《C#多线程编程实战(原书第2版)》——3.2 在线程池中调用委托
本節(jié)書摘來自華章出版社《C#多線程編程實戰(zhàn)(原書第2版)》一書中的第3章,第3.2節(jié),作者(美)易格恩·阿格佛溫(Eugene Agafonov),黃博文 黃輝蘭 譯,更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“華章計算機”公眾號查看。
3.2 在線程池中調(diào)用委托
本節(jié)將展示在線程池中如何異步的執(zhí)行委托。另外,我們將討論一個叫做異步編程模型(Asynchronous Programming Model,簡稱APM)的方式,這是.NET歷史中第一個異步編程模式。
3.2.1 準(zhǔn)備工作
為了學(xué)習(xí)本節(jié),你需要安裝Visual Studio 2015。除此之外無需其他準(zhǔn)備。本節(jié)的源代碼放置在BookSamplesChapter3Recipe1目錄中。
3.2.2 實現(xiàn)方式
請執(zhí)行以下步驟來了解如何在線程池中調(diào)用委托:
1.啟動Visual Studio 2015。新建一個C#控制臺應(yīng)用程序項目。
2.在Program.cs文件中加入以下using指令:
3.在Main方法下面加入以下代碼片段:
4.在Main方法中加入以下代碼片段:
5.運行程序。
3.2.3 工作原理
當(dāng)程序運行時,使用舊的方式創(chuàng)建了一個線程,然后啟動它并等待完成。由于線程的構(gòu)造函數(shù)只接受一個無任何返回結(jié)果的方法,我們使用了lambda表達式來將對Test方法的調(diào)用包起來。我們通過打印出Thread. CurrentThread.IsThreadPoolThread屬性值來確保該線程不是來自線程池。我們也打印出了受管理的線程ID來識別代碼是被哪個線程執(zhí)行的。
然后定義了一個委托并調(diào)用BeginInvoke方法來運行該委托。BeginInvoke方法接受一個回調(diào)函數(shù)。該回調(diào)函數(shù)在異步操作完成后會被調(diào)用,并且一個用戶自定義的狀態(tài)會傳給該回調(diào)函數(shù)。該狀態(tài)通常用于區(qū)分異步調(diào)用。結(jié)果,我們得到一個實現(xiàn)了IAsyncResult接口的result對象。BeginInvoke立即返回了結(jié)果,當(dāng)線程池中的工作者線程在執(zhí)行異步操作時,仍允許我們繼續(xù)其他工作。當(dāng)需要異步操作的結(jié)果時,可以使用BeginInvoke方法調(diào)用返回的result對象。我們可以使用result對象的IsCompleted屬性輪詢結(jié)果。但是在本例子中,使用的是AsyncWaitHandle屬性來等待直到操作完成。當(dāng)操作完成后,會得到一個結(jié)果,可以通過委托調(diào)用EndInvoke方法,傳遞委托參數(shù)和IAsyncResult對象。
事實上使用AsyncWaitHandle并不是必要的。如果注釋掉r.AsyncWaitHandle.WaitOne,代碼照樣可以成功運行,因為EndInvoke方法事實上會等待異步操作完成。調(diào)用EndInvoke方法(或者針對其他異步API的EndOperationName方法)是非常重要的,因為該方法會將任何未處理的異常拋回到調(diào)用線程中。當(dāng)使用這種異步API時,請確保始終調(diào)用了Begin和End方法。
當(dāng)操作完成后,傳遞給BeginInvoke方法的回調(diào)函數(shù)將被放置到線程池中,確切地說是一個工作者線程中。如果在Main方法定義的結(jié)尾注釋掉Thread.Sleep方法調(diào)用,回調(diào)函數(shù)將不會被執(zhí)行。這是因為當(dāng)主線程完成后,所有的后臺線程會被停止,包括該回調(diào)函數(shù)。對委托和回調(diào)函數(shù)的異步調(diào)用很可能會被同一個工作者線程執(zhí)行。通過工作者線程ID可以容易地看出。
使用BeginOperationName/EndOperationName方法和.NET中的IAsyncResult對象等方式被稱為異步編程模型(或APM模式),這樣的方法對稱為異步方法。該模式也被應(yīng)用于多個.NET類庫的API中,但在現(xiàn)代編程中,更推薦使用任務(wù)并行庫(Task Parallel Library,簡稱TPL)來組織異步API。第4章將會討論該主題。
總結(jié)
以上是生活随笔為你收集整理的《C#多线程编程实战(原书第2版)》——3.2 在线程池中调用委托的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: day04-装饰器
- 下一篇: 《Android应用开发攻略》——2.2