1. 程式人生 > >c#多執行緒與委託

c#多執行緒與委託

一:執行緒
在.net中提供了兩種啟動執行緒的方式,一種是不帶引數的啟動方式,另一種是帶引數的啟動的方式。
不帶引數的啟動方式
 如果啟動引數時無需其它額外的資訊,可以使用ThreadStart來例項化Thread:
 帶引數的啟動方法

帶引數,就不能用ThreadStart委託作為建構函式的引數來例項化Thread了,而要 ParameterizedThreadStart委託,和ThreadStart一樣的是它也是執行緒啟動時要執行的方法,和ThreadStart不同 的是,它在例項化時可以用一個帶有一個Object引數的方法作為建構函式的引數,而例項化ThreadStart時所用到的方法是沒有引數的。 為 什麼是Object這樣的引數呢?很簡單,因為在.net中Object是所有型別的基類,用它可以表示Array(陣列)、Interface(接 口)、ValueType(值型別,如bool,byte,char,short,int,float,long,double等)、class(類) 等.net中的型別。當然,這也意味著如果你要啟動一個執行緒,給它傳遞一個int型別引數時,必須在啟動方法中進行相應的型別轉換。
這種object型別的引數可以定義一個有多個屬性的類來進行,或者用$隔開的字串,使用的時候分解為陣列來用

簡單例項程式碼:
//不帶引數ThreadStart ts =newThreadStart(ThreadFunc);Thread t =newThread(ts);
t.Start();//帶引數 ParameterizedThreadStartParStart=newParameterizedThreadStart(GoTo);Thread myThread =newThread(ParStart);object o =(object)txt_url.Text;
myThread.Start(o);
詳細例項程式碼:
Program p =newProgram();Thread nonParameterThread 
=newThread(newThreadStart(p.NonParameterRun));  nonParameterThread.Start();Thread parameterThread =newThread(newParameterizedThreadStart(p.ParameterRun));  parameterThread.Name="Thread A:";  parameterThread.Start(30);/// <summary>/// 不帶引數的啟動方法/// </summary>publicvoidNonParameterRun(){for(int i =0; i
<10; i++){Console.WriteLine("系統當前時間毫秒值:"+DateTime.Now.Millisecond.ToString());Thread.Sleep(200);//讓執行緒暫停}}/// <summary>/// 帶引數的啟動方法/// </summary>/// <param name="ms">讓執行緒在執行過程中的休眠間隔</param>publicvoidParameterRun(object ms){int j =10;int.TryParse(ms.ToString(),out j);//這裡採用了TryParse方法,避免不能轉換時出現異常for(int i =0; i <10; i++){Console.WriteLine(Thread.CurrentThread.Name+"系統當前時間毫秒值:"+DateTime.Now.Millisecond.ToString());Thread.Sleep(j);//讓執行緒暫停}}
二:委託
委託就是講方法以引數的形式進行傳遞
privatestaticvoidWriteStrToFile(string txt){
write(txt);}privatedelegatevoidWriteStrToFileDelegate(string txt);//定義委託newWriteStrToFileDelegate(WriteStrToFile).BeginInvoke(txt,null,null);//非同步使用委託
再舉一例:
publicdelegatevoidGreetingDelegate(string name);//定義委託//定義兩方法privatestaticvoidEnglishGreeting(string name){Console.WriteLine("Morning, "+ name);}privatestaticvoidChineseGreeting(string name){Console.WriteLine("早上好, "+ name);}
使用:
privatestaticvoidGreetPeople(string name,GreetingDelegateMakeGreeting){MakeGreeting(name);//這裡默認同步方式,與MakeGreeting.Invoke(name)效果一樣}//使用GreetPeople("Jimmy Zhang",EnglishGreeting);GreetPeople("張子陽",ChineseGreeting);
實際上,我們可以也可以繞過GreetPeople方法,通過委託來直接呼叫EnglishGreeting和ChineseGreeting:
GreetingDelegate delegate1;
  delegate1 =EnglishGreeting;// 先給委託型別的變數賦值
  delegate1 +=ChineseGreeting;// 給此委託變數再繫結一個方法// 將先後呼叫 EnglishGreeting 與 ChineseGreeting 方法
  delegate1 ("Jimmy Zhang");Console.ReadKey();

委託的Invoke方法用來進行同步呼叫。同步呼叫也可以叫阻塞呼叫,它將阻塞當前執行緒,然後執行呼叫,呼叫完畢後再繼續向下進行。同步呼叫會阻塞執行緒,如果是要呼叫一項繁重的工作(如大量IO操作),可能會讓程式停頓很長時間,造成糟糕的使用者體驗,這時候非同步呼叫就很有必要了。
非同步呼叫不阻塞執行緒,而是把呼叫塞到執行緒池中,程式主執行緒或UI執行緒可以繼續執行。
委託的非同步呼叫通過BeginInvokeEndInvoke來實現。

比較:

在例項化Thread的例項,需要提供一個委託,在例項化這個委託時所用到的引數是執行緒將來啟動時要執行的方法。

委託其實也是一個執行緒

MethodInvoker mi =newMethodInvoker(DoPay);//定義委託this.BeginInvoke(mi);


這裡MethodInvoker
只是一個委託, 我們可以認為所有沒有引數的返回值為void的委託和 MethodInvoker 是一樣的, 他們都可以委託到沒有引數的返回值為void的方法。

你自己寫一個 Public Delegate Sub ABC, 這個時候ABC和MethodInvoker是完全一樣的。所以.Net 提供這個只是為了方便你編寫,省得你自己再寫一堆一樣的委託了。