我们在写 Remoting 程序或者其他的一些应用程序的时候难免要和线程打交道, .Net 使我们很容易就可以创建一个线程,但是它提供的创建线程和启动线程的方法没有明显的提供参数,假如我们要用线程来启动类里面一个带参数的方法该怎么办?下面就简单的介绍如何使用 .NET 提供的丰富的框架来实现这个功能。为了可以生动详细的介绍整个过程,我建立下面的一个 .NET 类,它也是要用线程启动的方法的载体。类如下所示:
using System;
namespace WindowsApplication1
{
///
1<summary>
2
3/// Summary description for UrlFetcher.
4
5/// </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 = "ParameterValue\n";
按钮事件如下所示:
// 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.MyMethod2),myParameter);
}
因为 QueueUserWorkItem 的二个参数是 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();
MyMethod3Delegate myMethod3 = new MyMethod3Delegate(instance.MyMethod3);
myMethod3.BeginInvoke("parameterValue",new AsyncCallback(AfterMyMothod3),null);
}
public void AfterMyMothod3(IAsyncResult result){
AsyncResult async = (AsyncResult) result;
MyMethod3Delegate DelegateInstance = (MyMethod3Delegate) 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.EventArgs e) {
MyClass instance = new MyClass();
MyMutilParamsDelegate mutilParams = new MyMutilParamsDelegate(instance.MyMutilParameters);
mutilParams.BeginInvoke("param1","params2",new AsyncCallback(AfterMutilParams),null);
}
public void AfterMutilParams(IAsyncResult result){
AsyncResult async = (AsyncResult) result;
MyMutilParamsDelegate DelegateInstance = (MyMutilParamsDelegate) async.AsyncDelegate;
Console.WriteLine (" 多参数函数调用返回结果: {0}\n", DelegateInstance.EndInvoke(result));
}
由于篇幅关系代码就不作详细说明了。有不正确的地方请指正,谢谢阅读!联系方式: [email protected] CSDN 论坛 ID : cuike519
参考文档: