C#多線程和非同步(三)——一些非同步編程模式

來源:互聯網
上載者:User

標籤:長度   int   div   hello   main   字元   一個   介面   one   

一、工作平行程式庫

  工作平行程式庫(Task Parellel Library)是BCL中的一個類庫,極大地簡化了並行編程,這裡以Parallel.For和Parallel.ForEach為例。在C#中for/foreach迴圈使用十分普遍,如果迭代不依賴與上次迭代的結果時,把迭代放在 不同的處理器上平行處理 將很大地提高運行效率,Parallel.For和Parallel.ForEach就是為這個目的而設計的。

一個栗子:

 1      static void Main(string[] args) 2         { 3             //Parallel.For  計算0到10的平方 4             Parallel.For(1, 6, i => 5             { 6                 Console.WriteLine("The square of {0} is {1}", i, i * i); 7             }); 8  9             //Parallel.ForEach 計算每個字串的長度10             string[] strs = { "We", "hold", "these", "truths" };11             Parallel.ForEach(strs, i => Console.WriteLine("{0} has {1} letters",i,i.Length));12             Console.ReadKey();13         }

運行結果:

 

 二、計時器(Timer)

  計時器提供了一種 定期重複運行非同步方法呼叫 的方式,當計時器到期後,系統從線程池中的線程上開啟一個回調方法,把state作為參數,並開始運行。

Timer最常用的建構函式如下:

Timer(TimeCallback callback,object state,uint dueTime, uint period)

callback是一個傳回值為void的委託,state為傳入callback的參數,dueTime為第一次調用前的時間,period為兩次調用的時間間隔

 一個栗子:

 1  class Program 2     { 3         int count = 0; 4         void Run(object state) 5         { 6             Console.WriteLine("{0},已經調用了{1}次了", state, ++count); 7         } 8         static void Main(string[] args) 9         {10             Program p = new Program();11             //2000毫秒後開始調用,每次間隔1000毫秒12             Timer timer = new Timer(p.Run, "hello", 2000, 1000);13             Console.WriteLine("Timer start");14             15             Console.ReadLine();16         }17     }

執行結果:

 三、委託執行非同步

  使用委託執行非同步,使用的是引用方法,如果一個委派物件在調用列表中只有一個方法(這個方法就是引用方法),它就可以非同步執行這個方法。委託類有兩個方法BeginIvoke和EndInvoke。

   BeginInvoke :執行BeginInvoke方法時,會線程池中擷取一個獨立線程來執行引用方法,並立即返回到原始線程一個實現IAsyncResult介面的對象的引用(該對象包含了線程池中線程運行非同步方法呼叫的狀態),原始線程繼續執行,而引用方法線上程池的線程中並存執行。

   EndInvoke  : 擷取非同步方法呼叫調用返回的值,並釋放資源,該方法把非同步方法呼叫的傳回值作為自己的傳回值。

委託執行非同步編程的3種模式:

  等待一直到完成(wait-until-done):在發起了非同步方法呼叫,原始線程執行到EndInvoke時就中斷並且等非同步方法呼叫完成完成後再繼續。

  輪詢(polling):原始線程定期檢查發起的線程是否完成(通過IAsyncResult.IsCompleted屬性判斷),如果沒有則繼續進行原始線程中的任務。

  回調(callback):原始線程一直執行,無需等待或檢查發起的線程是否完成,在發起的線程中的引用方法完成之後,發起線程會調用回調方法,由回調方法在調用EndInvoke之前處理非同步方法呼叫的結果。

 

①等待一直到完成模式

  原始線程執行到EndInvoke,如果非同步任務沒有完成就一直等待

 1     delegate int MyDel(int first,int second);//委託聲明 2     class Program 3     { 4         static int Sum(int x, int y) 5         { 6             Thread.Sleep(1000); 7             return x + y; 8         } 9         static void Main(string[] args)10         {11             MyDel del = Sum;12             //調用非同步作業(第三個參數是回呼函數,第四個參數是額外的值)13             IAsyncResult iar = del.BeginInvoke(3, 5, null, null);14             15             //doSomehing...16             17             //☆☆☆  執行EndInvoke,如果引用方法Sum沒有執行完成,主線程就等待其完成18             int result = del.EndInvoke(iar);19             Console.WriteLine(result);20         }21     }
 ②輪詢模式

  定期查詢任務是否完成:

 1     delegate int MyDel(int first,int second);//委託聲明 2     class Program 3     { 4         static int Sum(int x, int y) 5         { 6             Thread.Sleep(1000); 7             return x + y; 8         } 9         static void Main(string[] args)10         {11             MyDel del = Sum;12             IAsyncResult iar = del.BeginInvoke(3, 5, null, null);13             14             //☆☆☆ 通過iar.IsCompleted定期查詢完成狀態15             while (!iar.IsCompleted)//IsCompleted表示調用的非同步作業是否完成16             {17                 //doSomething18                 Thread.Sleep(300);19                 Console.WriteLine("no done");20             }21             int result = del.EndInvoke(iar);22             Console.WriteLine(result);23             Console.ReadKey();24         }25     }

③回調模式

原始線程執行委託的BeginInvoke後就不管新線程的事了,委託中的引用方法執行完成後,在回呼函數中擷取結果並處理,執行委託的EndInvoke方法

 1     delegate int MyDel(int first,int second);//委託聲明 2     class Program 3     { 4         static int Sum(int x, int y) 5         { 6             Thread.Sleep(1000); 7             return x + y; 8         } 9         10         //回調方法的簽名和傳回值類型必須和AsyncCallBack委託類型一致11         //輸入參數為IAsyncResult,傳回值是Void類型12        static void CallWhenDone(IAsyncResult iar){13            AsyncResult ar = (AsyncResult)iar;14            MyDel del = (MyDel)ar.AsyncDelegate;15            int result = del.EndInvoke(iar);16            Console.WriteLine("回呼函數執行EndInvoke");17            Console.WriteLine("result:{0}", result);18            Console.WriteLine("回呼函數完成");19         }     20         21         static void Main(string[] args)22         {23             MyDel del = Sum;24             //執行BeginInvoke方法後原始線程就不用管了,在自訂的回呼函數(CallWhenDone)中執行EndInvoke方法25             IAsyncResult iar = del.BeginInvoke(3, 5, CallWhenDone, null);26             Console.WriteLine("開啟新線程,非同步任務完成後執行回呼函數");27             //doSomething28             Console.WriteLine("回調執行不阻塞原始線程");29             Console.ReadKey();30         }31     }

執行結果:

還有一些其他的非同步編程模式如BackgroundWorker這裡不再細說了。

 

 

  

 

C#多線程和非同步(三)——一些非同步編程模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.