[轉(zhuǎn)]http://kb.VEVb.com/a/888688/
本片文章的議題是有關(guān)于傳遞參數(shù)到線程的幾種方法。
首先我們要知道什么是線程,什么時候要用到線程,如何去使用線程,如何更好的利用線程來完成工作。線程是程序可執(zhí)行片段的最小單元,是組成運行時程序的基本單元,一個進(jìn)程有至少一個線程組成。一般在并行處理等待事件的時候要用到線程,如等待網(wǎng)絡(luò)響應(yīng),等待I/O通訊,后臺事務(wù)處理等情況。使用線程其實很簡單,在.net框架下面你首先要定義一個函數(shù)來完成一些工作,然后實例化一個線程對象Thread thrd = new Thread(new ThreadStart(線程函數(shù))); 其中ThreadStart是一個不帶參數(shù)的函數(shù)委托。最后使用thrd.Start()就可以啟動線程了。當(dāng)然這只是一個很簡單的例子,實際中使用線程會有很多的問題要解決,比如傳遞參數(shù)到線程中,等待線程返回,如何同步線程進(jìn)行同一資源訪問,如何防止死鎖和競爭條件,如何有效的利用線程池,如何提供線程效率等問題。本文在這里將只對傳遞參數(shù)到線程進(jìn)行探討。
在上面舉例中我們看到線程實例化的參數(shù)是一個不帶任何參數(shù)的函數(shù)委托,那么就證明了我們不可能通過這樣一個委托傳遞參數(shù)到線程內(nèi)部。那么我們該怎么做呢?就我目前所知有三種方法可以實現(xiàn):1. 利用線程實現(xiàn)類,將調(diào)用參數(shù)定義成屬性的方式來操作線程參數(shù);2. 利用ParameterizedThreadStart委托來傳遞輸入?yún)?shù);3. 利用線程池來實現(xiàn)參數(shù)傳入。
1. 創(chuàng)建線程實現(xiàn)類,這種方式有個最大的優(yōu)點就是可以通過線程返回多個返回值假設(shè)存在在一個打印功能的線程,通過主函數(shù)傳入打印的行,列和字符數(shù)據(jù),并返回打印的字符總數(shù)。 class ThreadOutput { int _rowCount = 0; int _colCount = 0; char _char = '*'; int _ret = 0;
/**//// <summary> /// 輸入?yún)?shù) /// </summary> public int RowCount { set { _rowCount = value; } }
public int ColCount { set { _colCount = value; } }
public char Character { set { _char = value; } }
/**//// <summary> /// 輸出參數(shù) /// </summary> public int RetVal { get { return _ret; } }
public void Output() { for (int row = 0; row < _rowCount; row++) { for (int col = 0; col < _colCount; col++) { Console.Write("{0} ", _char); _ret++; } Console.Write("/n"); } }
ThreadOutput to1 = new ThreadOutput(); to1.RowCount = 10; to1.ColCount = 20;
Thread thrd = new Thread(new ThreadStart(to1.Output)); // 設(shè)置為后臺線程,主要是為不影響主線程的結(jié)束 thrd.IsBackground = true; thrd.Start();最后要注意的是由于線程實現(xiàn)類是通過屬性來傳遞數(shù)值的,那么在屬性訪問器中要進(jìn)行線程同步,否則取得的值可能不正確。
2. 利用ParameterizedThreadStart委托來傳遞輸入?yún)?shù)ParameterizedThreadStart委托是.Net2.0中才有的。該委托提供來在啟動線程時傳遞一個object參數(shù)到線程中。這種方式使用起來比較簡單,但是由于需要對object對象進(jìn)行類型轉(zhuǎn)換,所以存在類型不一致的隱患。
3. 利用線程池來實現(xiàn)參數(shù)傳入什么是線程池,線程池是系統(tǒng)提供一個存放線程的容器,進(jìn)入線程池后的線程控制權(quán)由系統(tǒng)掌握。利用線程池的好處是我們無需為線程存在大量空閑時間而去思考干點別的什么,適合于常規(guī)性的事務(wù)處理。在.Net中線程池是一個static類,所以我們需要通過ThreadPool來調(diào)用相關(guān)的函數(shù)。其中向線程池中加入線程的函數(shù)就是ThreadPool.QueueUserWorkItem(new WaitCallBack(), object obj)。這個函數(shù)有個WaitCallBack的委托,[ComVisibleAttribute(true)]public delegate void WaitCallback(Object state)通過這個委托我們也可以傳遞參數(shù)到線程中。
其實還有一種方法可以傳遞參數(shù)到線程中,那就是通過回調(diào)函數(shù)來實現(xiàn),只不過這種方法本質(zhì)上和第一種通過類的數(shù)據(jù)成員來傳遞參數(shù)的機制一樣。所以就不再細(xì)說來!
具體的實現(xiàn)可以參考下面的源代碼:
全部源代碼如下:(vs 2005編譯通過)1using System;2using System.Collections.Generic;3using System.Text;4using System.Threading;56namespace UsingThread7{8 struct RowCol9 {10 public int row;11 public int col;12 };1314 class ThreadOutput15 {16 // 建立等待時間17 static public ManualResetEvent PRompt = new ManualResetEvent(false);1819 int _rowCount = 0;20 int _colCount = 0;21 char _char = '*';22 int _ret = 0;2324 /**//// <summary>25 /// 輸入?yún)?shù)26 /// </summary>27 public int RowCount28 {29 set { _rowCount = value; }30 }3132 public int ColCount33 {34 set { _colCount = value; }35 }3637 public char Character38 {39 set { _char = value; }40 }4142 /**//// <summary>43 /// 輸出參數(shù)44 /// </summary>45 public int RetVal46 {47 get { return _ret; }48 }4950 public void Output()51 {52 for (int row = 0; row < _rowCount; row++)53 {54 for (int col = 0; col < _colCount; col++)55 {56 Console.Write("{0} ", _char);57 _ret++;58 }59 Console.Write("/n");60 }61 // 激活事件62 prompt.Set();63 }6465 public void Output(Object rc)66 {67 RowCol rowCol = (RowCol)rc;68 for (int i = 0; i < rowCol.row; i++)69 {70 for (int j = 0; j < rowCol.col; j++)71 Console.Write("{0} ", _char);72 Console.Write("/n");73 }74 }75 }7677 class Program78 {79 static void Main(string[] args)80 {81 ThreadOutput to1 = new ThreadOutput();82 to1.RowCount = 10;83 to1.ColCount = 20;8485 Thread thrd = new Thread(new ThreadStart(to1.Output));86 // 設(shè)置為后臺線程,主要是為不影響主線程的結(jié)束87 thrd.IsBackground = true;88 thrd.Start();8990 // 建立事件等待91 ThreadOutput.prompt.WaitOne();9293 Console.WriteLine("{0}", to1.RetVal);9495 ThreadOutput to2 = new ThreadOutput();96 to2.RowCount = 5;97 to2.ColCount = 18;98 to2.Character = '^';99 Thread thrds = new Thread(new ThreadStart(to2.Output));100 thrds.IsBackground = true;101 thrds.Start();102 thrds.Join();103104 Console.WriteLine("{0}", to2.RetVal);105106 // 傳遞參數(shù)給線程的另一種實現(xiàn)107 RowCol rc = new RowCol();108 rc.row = 12;109 rc.col = 13;110 to1.Character ='@';111 if (ThreadPool.QueueUserWorkItem(new WaitCallback(to1.Output), rc))112 Console.WriteLine("Insert Pool is success!");113 else114 Console.WriteLine("Insert Pool is failed!");115 Thread.Sleep(1000);116117118 // 使用新的ThreadStart委托來傳遞參數(shù)119 rc.col = 19;120 to2.Character = '#';121 Thread thrdt = new Thread(new ParameterizedThreadStart(to2.Output));122 thrdt.Start(rc);123 thrdt.Join();124 }125126 }127}128
新聞熱點
疑難解答