我們在寫Remoting程式或其他的一些應用程式的時候難免要和線程打交道,.Net使我們很容易就可以創建一個線程,但是它提供的創建線程和啟動線程的方法沒有明顯的提供參數,假如我們要用執行緒來啟動類別裡面一個帶參數的方法該怎麼辦?以下就簡單的介紹如何使用.NET提供的豐富的框架來實現這個功能。為了可以生動詳細的介紹整個過程,我建立下面的一個.NET類,它也是要用執行緒啟動的方法的載體。類別如下圖所示:
using System;
namespace WindowsApplication1
{
/// <summary>
/// Summary description for UrlFetcher.
/// </summary>
public class MyClass{
// for method 1
private string _parameter;
public MyClass(string parameter){
this._parameter = parameter;
}
public void MyMethod1(){
if(this._parameter!=null){
// do something
Console.Write(this_parameter );
}
}
// for method 2
public MyClass(){}
// this method is private,But it can be public or other
private void MyMethod2(string parameter){
// do something
Console.Write(parameter);
}
// Because delegate WaitCallback's parameter Type is object
// I will convert it to string.
public void MyMethod2(object parameter){
this.MyMethod2((string)parameter);
}
// for method 3
public string MyMethod3(string parameter){
return "參數值為:"+parameter;
}
// for mutil-parameters passed
public string MyMutilParameters(string param1,string param2){
return "參數1與參數2連線結果為:"+param1+param2;
}
}
}
嘿嘿,我的英文不行,註解寫的不好請見諒(因為使用的是英文的),希望沒有影響您的閱讀。我想我有必要簡單的說一下上面這個類別裡面的所包含的內容。首先包含兩個建構函數,一個帶參數一個不帶(這裡可是有意安排的)。透過類別中其他方法的名字我想您一定猜出來我將介紹3種方法來傳遞參數,接下來我將逐一介紹。首先我們來看看如何啟動一個線程,首先我們可以用一個函數來實例化ThreadStart委託的一個實例,然後在使用這個實例作為參數new線程(Thread)對象,最後將這個線程Start就可以了,想了解更多請參考MSDN文檔的Thread部分。
為了測試我們的結果我建立了一個WinForm的工程,其中有一個Form和4個按鈕,如果你需要所有的源碼請發送郵件到[email protected] ,如果我有時間我會給你發過去的。接下來是每種方法的詳細描述。
1.使用建構子來傳遞參數
眾所周知,我們可以使用一個帶參數的建構子來建構對象,既然這樣我們可以利用建構子先將要使用的參數值傳遞到對象裡面的內部變數上,然後再使用一個無參數的方法來使用這個參數(假裝參數)。簡單的說就是,在類別裡面宣告一個變數專門用來保存函數所需的參數,函數變成無參的形式。這種方法的最大問題就是破壞了封裝性,雖然我們不能直接方法這些變數但是隱性總是存在的(或者說看起來不爽都可以)。下面程式碼片段給出瞭如何使用這個方法來傳遞參數的詳細內容,這也是上面提到的4個按鈕中的一個按鈕(Button1)的Click程式碼。為了有參數可傳我在WinForm全域定義了一個如下的變數:
// This is parameter's value
private string myParameter = "ParameterValuen";
按鈕事件如下所示:
// passed parameters to thread by construct
private void button1_Click object sender, System.EventArgs e) {
MyClass instance = new MyClass(myParameter);
new Thread (new ThreadStart(instance.MyMethod1)).Start();
}
如同上面所說的,我們使用建構子將參數傳遞到類別裡面去,然後在使用上面所說的方法啟動了一個線程,我們可以在運行該程式後的output視窗中看到MyMethod1的執行結果是(你也可以用一個TextBox或其他東西直接顯示在WinForm上) :ParameterValue 。看看函數體就知道這個結果是正確的。是不是很簡單。
2.使用ThreadPool來實現
參數的傳遞我們首先可以看看MSDN對ThreadPool是怎麼形容的,Provides a pool of threads that can be used to post work items, process asynchronous I/O, wait on behalf of other threads, and process timers.查看它的方法集合其中有一個叫:QueueUserWorkItem 的方法,該類別以及該方法的詳細資訊請參考MSDN相關幫助。這裡要注意的就是QueueUserWorkItem方法的參數,參數WaitCallback是委託類型,第二個參數就是該委託實例(用函數實例化以後,也就是一個函數)所需要的參數,是object類型的。詳細內容請看下面的程式碼。
// passed parameter to thread by ThreadPool
private void button2_Click(object sender, System.EventArgs e) {
MyClass instance = new MyClass();
ThreadPool.QueueUserWorkItem (new WaitCallback (
instance
.
參數是object類型的所以我們要在MyClass裡面定義兩個MyMethod2的重裁版本,目的就是為了滿足方法的參數。同樣我們將參數myParameter傳遞進去了,運行程序,當我們點擊Button2的時候在output視窗中將會出現MyMethod2將myParameter作為參數執行的結果顯示出來。
3.接下來是最後一種方法使用非同步委託來實現參數的傳遞
同樣,有關委託的詳細資訊可以參考MSDN,上面說的非常詳細。我們這裡要使用BeginInvoke和EndInvoke方法。首先我們給傳遞一個參數的方法如下所示:
// passed parameter by asynchronous delegate
delegate string MyMethod3Delegate(string parameter);
private void button3_Click(object sender, System.EventArgs e) {
MyClass instance = new MyClass(object sender, System.EventArgs e) {MyClass
instance = new MyClass );
myMethod3 = new MyMethod3Delegate(instance.MyMethod3);
myMethod3.BeginInvoke("parameterValue",new AsyncCallback(
AfterMyMothod3),null);
}
public void AfterMyMothod3(IAsyncResult result){ Asfidenceal
3Delegate) async.AsyncDelegate;
Console.WriteLine ("函數呼叫回傳值:{0}n", DelegateInstance.EndInvoke(result));
}
首先為了使用委託我們聲明了一個MyMethod3Delegate的委託,該委託說明一個參數和傳回值為string的函數是符合條件的,所以我們在MyClass裡面定義了一個MyMethod3的方法。這個函數的型構符合上面的委託,所以我們可以在Button3點擊的時候用這個方法實例化一個委託,然後我們使用非同步的方式呼叫這個方法,為了得到返回結果我們寫了AfterMyMothod3方法用來顯示該函數的執行結果。運行程式點選Button3可以看到Output中輸出的結果為MyMethod3帶參數執行的結果。最後我給出如何傳遞多個參數的方法,我的例子是傳遞2個參數。程式碼如下:
// mutil-parameters passed
delegate string MyMutilParamsDelegate(string parameter1,string parameter2);
private void button4_Click(object sender, System. MyArgs e) { MyClass nce = newinstances
;
tilParameters );
mutilParams.BeginInvoke("param1","params2",new AsyncCallback(AfterMutilParams),null);
}
public void AfterMutilParams(IAsyncResult result){
AsyncResult async = (AsyncResult) result;
MyMutilParamsDelegate DelegateInstance = (MyMutilParamsDelegate) async.Asyncelegate;
InstanceD ));
}
由於篇幅關係程式碼就不作詳細說明了。有不正確的地方請指正,謝謝閱讀!聯絡方式: [email protected] CSDN論壇ID:cuike519
參考文件:
http: