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 = new ThreadStart(ThreadFunc); Thread t = new Thread(ts); t.Start(); //帶參數  ParameterizedThreadStart ParStart = new ParameterizedThreadStart(GoTo); Thread myThread = new Thread(ParStart); object o = (object)txt_url.Text; myThread.Start(o);

詳細實例代碼:

Program p = new Program();  Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun));  nonParameterThread.Start();  Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));  parameterThread.Name = "Thread A:";  parameterThread.Start(30);                                  /// <summary>                  /// 不帶參數的啟動方法                  /// </summary>                  public void NonParameterRun()                  {                          for (int i = 0; i < 10; i++)                          {                                  Console.WriteLine("系統當前時間毫秒值:"+DateTime.Now.Millisecond.ToString());                                  Thread.Sleep(200);//讓線程暫停                          }                 }                 /// <summary>                  /// 帶參數的啟動方法                  /// </summary>                  /// <param name="ms">讓線程在運行過程中的休眠間隔</param>                  public void ParameterRun(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);//讓線程暫停                          }                  }

二:委托
委托就是講方法以參數的形式進行傳遞

private static void WriteStrToFile(string txt) { write(txt); } private delegate void WriteStrToFileDelegate(string txt);//定義委托 new WriteStrToFileDelegate(WriteStrToFile).BeginInvoke(txt, null, null);//異步使用委托

再舉一例:

public delegate void GreetingDelegate(string name);//定義委托 //定義兩方法 private static void EnglishGreeting(string name) {  Console.WriteLine("Morning, " + name); } private static void ChineseGreeting(string name) {  Console.WriteLine("早上好, " + name); }

使用:

private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {   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線程可以繼續執行。
委托的異步調用通過BeginInvoke和EndInvoke來實現。

比較:
在實例化Thread的實例,需要提供一個委托,在實例化這個委托時所用到的參數是線程將來啟動時要運行的方法。

委托其實也是一個線程

 

 

MethodInvoker mi = new MethodInvoker(DoPay);//定義委托             this.BeginInvoke(mi);

 


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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM