异步编程模式学习
????? 最近,在學習C#多線程編程,也看了園子里的很多大牛的關于多線程的文章,梳理下自己的思路,也總結下異步編程模式的學習。
?????很喜歡Jimmy Zhang的文章風格,在剛剛學習委托和事件的時候,Jimmy的文章的由淺入深的寫作對我對委托和事件的學習的幫助很大。我也學這個Jimmy的文風,和大家交流下。廢話不多說的,通過一個拋12點的小游戲的例子進入正題。
????沒有異步模式的多線程實現????????????????????????
?????? 游戲的規則:游戲隨機產生的0到12之間的數字,碰到數字12游戲結束。實現如下:例1
static void Main(string[] args){Thread thread = new Thread(new ThreadStart(ThreadFun));thread.Start();Console.WriteLine("Game is starting...");thread.Join();Console.WriteLine("Number 12 is createed.Game is over...");Console.ReadKey();}static void ThreadFun(){Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}?
?????? 異步編程模式的實現
?這個小游戲的異步模式編程實現如下代碼:例2
delegate void asycInvoker();static void Main(string[] args){asycInvoker asycHander = ThreadFun;//此處是asycInvoker asycHander = new asycInvoker(ThreadFun)的快捷語法IAsyncResult result = asycHander.BeginInvoke(null,null);Console.WriteLine("Game is starting...");asycHander.EndInvoke(result);Console.WriteLine("Number 12 is createed.Game is over...");Console.ReadKey();}static void ThreadFun(){Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}??? 異步編程模式和多線程的關系
???? 異步編程模式技術為多線程處理技術的強大擴展方式。C#的異步模式的內部的實現是通過線程池的掛起和釋放實現一步操作。C#的異步模式的好處降低創建和銷毀線程相關的成本,CLR為每一個進程維護一個線程池。
???? 由此,我們必須清楚線程池的優缺點的。線程池的優點是很明顯的,缺點是一旦加入線程池,就沒辦法控制程序的執行,程序的執行都在線程池的自動管理。
?? .NET的異步編程模式
????? Net 在設計的時候為異步編程設計了一個異步編程模型(APM),這個模型不僅是使用.NET的開發人員使用,.Net內部也頻繁用到。通過使用委托,我們可以異步實現委托列表上的方法(委托列表只能有一個方法)。委托類有兩個方法:叫做BeginInvoke和EndInvoke,他們就是用來實現異步操作過程。
????? 當我們調用委托的BeginInvoke方法時,它開始在線程池中的獨立線程上執行引用方法,并且立即返回原始線程。原始線程可以繼續,而引用方法會在線程池的線程中執行。
???? 當程序異步方法執行的時候,主線程和異步方法的線程池線程之間的同步過程不同處理,就會有不同的實現模式,當異步方法執行結束,可以檢查BeginInvoke返回的IAsyncResult的IsCompleted屬性,或者調用委托的EndInvoke方法等待委托的完成,或著在委托的回調方法中調用EndInvoke方法完成委托。
???? 上述過程有異步編程的3種標準模式的過程。這三種過程,原始線程都發起了一個異步方法,這些模式不同的是,原始線程獲得發起的線程已經完成的消息的方式。標準的三種模式有等待完成模式、輪詢模式和回調模式。通過代碼將每一種模式表述下:
????? 等待-結束模式
???? 在這個模式中,原始線程發起異步模式方法的調用,原始線程和異步方法所在的線程池線程并發(可能這里用并發描述不是很恰當)運行,如果原始線程一直到調用委托方法的EndInvoke時,委托方法還沒有執行完,原始線程就等待異步線程結束,如果有返回值的話,返回異步方法的返回值。代碼如例1所示。
???? AsyncResult類
?????? 在BeginInvoke方法的調用的時候,返回一個IAsyncResult接口的引用,在內部實現AsyncResult類的對象。AsyncResult類表現了異步方法的狀態。有關這個類的需要說明的如下:
- ?我們調用委托對象的BeginInvoke方法時,系統創建了一個AsyncResult類的對象。BeingInvoke方法返回對象實現的接口的引用。
- AsyncResult對象包含一個叫做AsyncDelegate的屬性,該屬性返回指向被調用的產生異步方法的委托對象的引用。
- IsCompleted屬性表示異步方法是否完成。
- AsyncState屬性作為BeginInvoke方法調用時的state參數,他返回object類型的引用。
?
????輪詢模式
?????? 在輪詢模式中,原始線程發起的異步方法的調用,原始線程就繼續執行,然后用IasyncResult的IsComplete屬性來定期檢查異步線程是否完成。如果異步方法已經完成,原始線程就調用EndInvoke并繼續,否則,繼續檢查執行。代碼實例3
delegate void asycInvoker();static void Main(string[] args){asycInvoker asycHander = new asycInvoker(ThreadFun);IAsyncResult result = asycHander.BeginInvoke(null,null);Console.WriteLine("Game is starting...");while (!result.IsCompleted){Console.WriteLine("Game is not completed...");//此處可以繼續執行其他的邏輯 }asycHander.EndInvoke(result);Console.WriteLine("Number 12 is createed.Game is over...");Console.ReadKey();}static void ThreadFun(){Thread.Sleep(100);//暫時掛起該線程,放大整個執行的過程Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}?????回調模式
?????在前面的模式中,等待-結束和輪詢模式中,初始線程都是繼續自己的執行過程,等待異步的線程完成。然后,在EndInvoke獲得異步方法的返回值,并初始線程繼續后面的邏輯執行。在效率地上,輪詢通常不是最好的方法。所以,在異步編程中使用通知機制,能在一個異步方法完成時觸發一個方法。
????? 我們回到BeginInvoke方法的參數來談的,BeginInvoke的參數根據定義的委托類型不斷變化的,但是最后兩個參數是不會改變的,AsyncCllback委托類型的原型為:delegate void AsyncCallback(IAsyncResult result),最后一個參數為object類型,稍后會談到object類型解決的問題。回調的方法的通知機制關鍵就在AsyncCllback委托類型參數的使用,在AsyncCallback委托的實例中調用EndInvoke方法,返回異步方法的返回值,而AsyncCallback實例在異步方法一結束就調用。通過代碼演練實例4:
delegate void asycInvoker();static void Main(string[] args){asycInvoker asycHander = new asycInvoker(ThreadFun);IAsyncResult result = asycHander.BeginInvoke(new AsyncCallback(CallbackFun),null);Console.WriteLine("Game is starting...");Console.ReadKey();}static void CallbackFun(IAsyncResult result){AsyncResult asyncResult = (AsyncResult)result;asycInvoker handler = (asycInvoker)asyncResult.AsyncDelegate;handler.EndInvoke(result);Console.WriteLine("Number 12 is createed.Game is over...");}static void ThreadFun(){Console.WriteLine("asyncMethod is runing...");Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}回調過程傳遞參數
?????? 為能具體的展示object類型參數的應用,這次將這個小程序的要求改變一下,我們可以隨機選擇結束的數字,游戲在產生我們需要的數字時結束。通過代碼的演示例5
delegate void asycInvoker(int endNum);static void Main(string[] args){Console.WriteLine("Select the End Number:");int endNum = int.Parse(Console.ReadLine());asycInvoker asycHander = new asycInvoker(ThreadFun);IAsyncResult result = asycHander.BeginInvoke(endNum,new AsyncCallback(CallbackFun),endNum);Console.WriteLine("Game is starting...");Console.ReadKey();}static void CallbackFun(IAsyncResult result){int endNum = (int)result.AsyncState;AsyncResult asyncResult = (AsyncResult)result;asycInvoker handler = (asycInvoker)asyncResult.AsyncDelegate;handler.EndInvoke(result);Console.WriteLine("Number {0} is createed.Game is over...",endNum);//此處為傳遞的參數的用途 }static void ThreadFun(int endNum){Console.WriteLine("asyncMethod is runing...");Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, endNum);Console.WriteLine(rndNum);} while (rndNum != 12);}???? 關于異步編程的使用,推薦老趙的博客寫到的正確使用異步操作。
????????以上是我對學習異步編程模式的知識的梳理,在大神云集的園子里,作為.NET入門新手,不求聞達,希望能為園子里樂于分享的精神能有所發揚,也希望能對園子里的新手們有所幫助,能得到牛人的指導。
?
?
???????
?
?
?
?
?
????
????
?
轉載于:https://www.cnblogs.com/Johnnie/archive/2012/08/20/Async.html
總結
- 上一篇: IIS相关问题及解决方案
- 下一篇: Android培训翻译_允许其他应用程序