使用.NET我们可以很容易的创建一个线程,但是它提供的创建线程和启动线程的方法没有明显的提供参数,假如我们要用线程来启动类里面一个带参数的方法该怎么办?下面介绍几种方法。
1.利用构造函数传递参数
这种方法比较容易理解,我们在实例化线程要启动方法所在类时将方法所需的参数传递给类的构造函数,并将其赋值给类的成员变量,这样在方法中就可以使用该变量了,从而达到将参数传递给方法的目的。
class ThreadParameters
{
public static void Main(string[] args)
{
AnimalShower dog = new AnimalShower("dog");
AnimalShower cat = new AnimalShower("cat");
Thread t1 = new Thread(new ThreadStart(dog.DoShower));
Thread t2 = new Thread(new ThreadStart(cat.DoShower));
t1.Start();
t2.Start();
Console.ReadLine();
}
}
//利用构造函数传递线程参数
public class AnimalShower
{
private string name;
public AnimalShower(string name)
{
this.name = name;
}
public void DoShower()
{
Console.WriteLine(this.name + " begin to shower");
//线程随机Sleep一段时间,模拟处理过程
Thread.Sleep(new Random().Next(1000, 2500));
Console.WriteLine(this.name + " end to shower");
}
}
2.利用ThreadPool类来传递线程参数
ThreadPool类提供一个由系统维护的线程池(可以看作一个线程的容器)。ThreadPool类有一个静态方法QueueUserWorkItem,它将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。函数QueueUserWorkItem和委托WaitCallback原型如下:
/// <summary>
/// 将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。
/// </summary>
/// <param name="callBack">System.Threading.WaitCallback,它表示要执行的方法</param>
/// <param name="state">包含方法所用数据的对象</param>
/// <returns>如果将方法成功排入队列,则为 true;否则为 false。</returns>
public static bool QueueUserWorkItem(WaitCallback callBack, object state)
//表示线程池线程要执行的回调方法
public delegate void WaitCallback(object state);
ThreadPool类适用于应用程序大部分时间花费在等待状态,等待某个事件的发生,然后给予响应,关于ThreadPool类更深入的解释可以参考博客园文章.NET 线程池编程技术。下面是使用ThreadPool类实现线程参数传递的示例:
class ThreadParameters
{
public static void Main(string[] args)
{
AnimalShower dog = new AnimalShower();
AnimalShower cat = new AnimalShower();
ThreadPool.QueueUserWorkItem(new WaitCallback(new AnimalShower().DoShower), "dog");
ThreadPool.QueueUserWorkItem(new WaitCallback(new AnimalShower().DoShower), "cat");
Console.ReadLine();
}
}
public class AnimalShower
{
public AnimalShower()
{
}
//为了能实例化委托WaitCallback,参数用Object类型
public void DoShower(object name)
{
Console.WriteLine(name.ToString() + " begin to shower");
//线程随机Sleep一段时间,模拟处理过程
Thread.Sleep(new Random().Next(1000, 2500));
Console.WriteLine(name.ToString() + " end to shower");
}
}
3.利用ParameterizedThreadStart委托实例化Thread类
ParameterizedThreadStart初始化Thread类的实例,指定允许对象在线程启动时传递给线程的委托。利用.NET Framework 2.0版新增Thread的构造函数public Thread(ParameterizedThreadStart start)可将参数传递给ThreadInstance.Start(Object parameter)方法,简单示例如下:
public static void Main(string[] args)
{
AnimalShower dog = new AnimalShower();
AnimalShower cat = new AnimalShower();
Thread t1 = new Thread(new ParameterizedThreadStart(dog.DoShower));
Thread t2 = new Thread(new ParameterizedThreadStart(cat.DoShower));
t1.Start("dog");
t2.Start("cat");
Console.ReadLine();
}
}
public class AnimalShower
{
public AnimalShower()
{
}
//为了能实例化委托ParameterizedThreadStart,参数用Object类型
public void DoShower(object name)
{
Console.WriteLine(name.ToString() + " begin to shower");
//线程随机Sleep一段时间,模拟处理过程
Thread.Sleep(new Random().Next(1000, 2500));
Console.WriteLine(name.ToString() + " end to shower");
}
}
总结:如果.NET Framework是2.0及以上版本,最好是在后两种方法中做出选择,因为第一种方法利用类的构造函数,破坏了类的封装性,而且有时代码会变的难以理解。如果是.NET Framework是2.0以下版本,只能在前面两种方法中做出选择。