標籤:長度 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#多線程和非同步(三)——一些非同步編程模式