本文匯總整理了傳遞參數到線程的方法供大家參考,非常實用,具體內容如下:
首先我們要知道什么是線程,什么時候要用到線程,如何去使用線程,如何更好的利用線程來完成工作。
線程是程序可執行片段的最小單元,是組成運行時程序的基本單元,一個進程有至少一個線程組成。一般在并行處理等待事件的時候要用到線程,如等待網絡響應,等待I/O通訊,后臺事務處理等情況。使用線程其實很簡單,在.net框架下面你首先要定義一個函數來完成一些工作,然后實例化一個線程對象Thread thrd = new Thread(new ThreadStart(線程函數)); 其中ThreadStart是一個不帶參數的函數委托。最后使用thrd.Start()就可以啟動線程了。當然這只是一個很簡單的例子,實際中使用線程會有很多的問題要解決,比如傳遞參數到線程中,等待線程返回,如何同步線程進行同一資源訪問,如何防止死鎖和競爭條件,如何有效的利用線程池,如何提供線程效率等問題。本文在這里將只對傳遞參數到線程進行探討。
在上面舉例中我們看到線程實例化的參數是一個不帶任何參數的函數委托,那么就證明了我們不可能通過這樣一個委托傳遞參數到線程內部。那么我們該怎么做呢?
就我目前所知有三種方法可以實現:1. 利用線程實現類,將調用參數定義成屬性的方式來操作線程參數;2. 利用ParameterizedThreadStart委托來傳遞輸入參數;3. 利用線程池來實現參數傳入。
下面分別加以敘述:
1. 創建線程實現類,這種方式有個最大的優點就是可以通過線程返回多個返回值
假設存在在一個打印功能的線程,通過主函數傳入打印的行,列和字符數據,并返回打印的字符總數。
具體代碼如下:
class ThreadOutput{int _rowCount = 0;int _colCount = 0;char _char = '*';int _ret = 0;/**//// <summary>/// 輸入參數 /// </summary>public int RowCount{ set { _rowCount = value; }}public int ColCount{ set { _colCount = value; }}public char Character{ set { _char = value; }}/**//// <summary>/// 輸出參數 /// </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));// 設置為后臺線程,主要是為不影響主線程的結束thrd.IsBackground = true;thrd.Start();
最后要注意的是由于線程實現類是通過屬性來傳遞數值的,那么在屬性訪問器中要進行線程同步,否則取得的值可能不正確。
2. 利用ParameterizedThreadStart委托來傳遞輸入參數
ParameterizedThreadStart委托是.Net2.0中才有的。該委托提供來在啟動線程時傳遞一個object參數到線程中。這種方式使用起來比較簡單,但是由于需要對object對象進行類型轉換,所以存在類型不一致的隱患。
3. 利用線程池來實現參數傳入
什么是線程池,線程池是系統提供一個存放線程的容器,進入線程池后的線程控制權由系統掌握。利用線程池的好處是我們無需為線程存在大量空閑時間而去思考干點別的什么,適合于常規性的事務處理。在.Net中線程池是一個static類,所以我們需要通過ThreadPool來調用相關的函數。其中向線程池中加入線程的函數就是ThreadPool.QueueUserWorkItem(new WaitCallBack(), object obj)。這個函數有個WaitCallBack的委托,[ComVisibleAttribute(true)]
public delegate void WaitCallback(Object state)
通過這個委托我們也可以傳遞參數到線程中。
其實還有一種方法可以傳遞參數到線程中,那就是通過回調函數來實現,只不過這種方法本質上和第一種通過類的數據成員來傳遞參數的機制一樣。所以就不再細說來!
具體的實現可以參考下面的源代碼:
全部源代碼如下:(該程序在vs 2005編譯通過)
using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace UsingThread{ struct RowCol { public int row; public int col; }; class ThreadOutput { // 建立等待時間 static public ManualResetEvent prompt = new ManualResetEvent(false); int _rowCount = 0; int _colCount = 0; char _char = '*'; int _ret = 0; /**//// <summary> /// 輸入參數 /// </summary> public int RowCount { set { _rowCount = value; } } public int ColCount { set { _colCount = value; } } public char Character { set { _char = value; } } /**//// <summary> /// 輸出參數 /// </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"); } // 激活事件 prompt.Set(); } public void Output(Object rc) { RowCol rowCol = (RowCol)rc; for (int i = 0; i < rowCol.row; i++) { for (int j = 0; j < rowCol.col; j++) Console.Write("{0} ", _char); Console.Write("/n"); } } } class Program { static void Main(string[] args) { ThreadOutput to1 = new ThreadOutput(); to1.RowCount = 10; to1.ColCount = 20; Thread thrd = new Thread(new ThreadStart(to1.Output)); // 設置為后臺線程,主要是為不影響主線程的結束 thrd.IsBackground = true; thrd.Start(); // 建立事件等待 ThreadOutput.prompt.WaitOne(); Console.WriteLine("{0}", to1.RetVal); ThreadOutput to2 = new ThreadOutput(); to2.RowCount = 5; to2.ColCount = 18; to2.Character = '^'; Thread thrds = new Thread(new ThreadStart(to2.Output)); thrds.IsBackground = true; thrds.Start(); thrds.Join(); Console.WriteLine("{0}", to2.RetVal); // 傳遞參數給線程的另一種實現 RowCol rc = new RowCol(); rc.row = 12; rc.col = 13; to1.Character = '@'; if (ThreadPool.QueueUserWorkItem(new WaitCallback(to1.Output), rc)) Console.WriteLine("Insert Pool is success!"); else Console.WriteLine("Insert Pool is failed!"); Thread.Sleep(1000); // 使用新的ThreadStart委托來傳遞參數 rc.col = 19; to2.Character = '#'; Thread thrdt = new Thread(new ParameterizedThreadStart(to2.Output)); thrdt.Start(rc); thrdt.Join(); } }}
新聞熱點
疑難解答