系列文章,从一个基本的代码说起,逐步探索 ThreadPool 的奥妙。
在上次的基础上,我需要做以下的事情:
1、要传递给线程的参数更加复杂;
2、线程要处理的工作更加多样;
3、在线程中我要改变主线程传入的参数,并告诉主程序。
好的,第一个问题,因为 WaitCallback 委托的原型决定了参数只能有一个 ( Object state ),那没有办法,我们只能将多个参数封装到一个Object 中,也就是 class 中。
第二个问题,要处理这个问题也很简单,就是再定义一个 WaitCallback 委托的对象,将它作为参数传递给ThreadPool.QueueUserWorkItem ()方法。这个对象可以在线程里面处理另外一类的工作。
代码如下:
using System;
using System.Threading;
public class App
{
public static void Main ( ) {
WaitCallback waitCallback = new WaitCallback ( MyThreadWork );
WaitCallback waitCallback2= new WaitCallback ( MyThreadWork2 ); // 增加线程工作类型
ThreadPool.QueueUserWorkItem ( waitCallback, "第一个线程" );
ThreadPool.QueueUserWorkItem ( waitCallback, "第二个线程" );
MyState myState = new MyState ( "第三个线程",100); // 增加自定义的线程参数类型
ThreadPool.QueueUserWorkItem ( waitCallback2, myState );
ThreadPool.QueueUserWorkItem ( waitCallback2, new MyState("第四个线程",2) );
Console.WriteLine ( "MyState 的 Number 值为: {0}", myState.Number ); // 读取线程改变后的 MyState
Console.ReadLine ( );
}
public static void MyThreadWork ( object state ) {
Console.WriteLine ( "MyThreadWork 开始启动 …… {0}", ( string ) state );
Thread.Sleep ( 10000 );
Console.WriteLine ( "运行结束…… {0}", ( string ) state );
}
// use MyState class
public static void MyThreadWork2 ( object state ) {
Console.WriteLine ( "MyThreadWork2 开始启动…… {0},{1}", ( ( MyState ) state ).Info, ( ( MyState ) state ).Number );
Thread.Sleep ( 10000 );
( ( MyState ) state ).Number += 1; // 将 state的 Number 加 1
Console.WriteLine ( "运行结束…… {0},{1}", ( ( MyState ) state ).Info, ( ( MyState ) state ).Number );
}
}
public class MyState
{
private string info;
private int number;
public MyState ( string info, int number ) {
this.info = info;
this.number = number;
}
public string Info {
get {
return this.info;
}
set {
this.info = value;
}
}
public int Number {
get {
return this.number;
}
set {
this.number = value;
}
}
}
using System.Threading;
public class App
{
public static void Main ( ) {
WaitCallback waitCallback = new WaitCallback ( MyThreadWork );
WaitCallback waitCallback2= new WaitCallback ( MyThreadWork2 ); // 增加线程工作类型
ThreadPool.QueueUserWorkItem ( waitCallback, "第一个线程" );
ThreadPool.QueueUserWorkItem ( waitCallback, "第二个线程" );
MyState myState = new MyState ( "第三个线程",100); // 增加自定义的线程参数类型
ThreadPool.QueueUserWorkItem ( waitCallback2, myState );
ThreadPool.QueueUserWorkItem ( waitCallback2, new MyState("第四个线程",2) );
Console.WriteLine ( "MyState 的 Number 值为: {0}", myState.Number ); // 读取线程改变后的 MyState
Console.ReadLine ( );
}
public static void MyThreadWork ( object state ) {
Console.WriteLine ( "MyThreadWork 开始启动 …… {0}", ( string ) state );
Thread.Sleep ( 10000 );
Console.WriteLine ( "运行结束…… {0}", ( string ) state );
}
// use MyState class
public static void MyThreadWork2 ( object state ) {
Console.WriteLine ( "MyThreadWork2 开始启动…… {0},{1}", ( ( MyState ) state ).Info, ( ( MyState ) state ).Number );
Thread.Sleep ( 10000 );
( ( MyState ) state ).Number += 1; // 将 state的 Number 加 1
Console.WriteLine ( "运行结束…… {0},{1}", ( ( MyState ) state ).Info, ( ( MyState ) state ).Number );
}
}
public class MyState
{
private string info;
private int number;
public MyState ( string info, int number ) {
this.info = info;
this.number = number;
}
public string Info {
get {
return this.info;
}
set {
this.info = value;
}
}
public int Number {
get {
return this.number;
}
set {
this.number = value;
}
}
}
在代码里面,我尝试对三个问题都进行解决,但是,很遗憾,上面的代码只是解决了第1、2个问题。
虽然,我的MyThreadWork2 () 线程尝试对 MyState 的 Number 进行加1操作,但是,主线程的输出仍然可能是 100,如下所示:
MyState 的 Number 值为: 100
MyThreadWork 开始启动 …… 第一个线程
MyThreadWork 开始启动 …… 第二个线程
MyThreadWork2 开始启动…… 第三个线程,100
MyThreadWork2 开始启动…… 第四个线程,2
运行结束…… 第一个线程
运行结束…… 第二个线程
运行结束…… 第三个线程,101
运行结束…… 第四个线程,3
MyThreadWork 开始启动 …… 第一个线程
MyThreadWork 开始启动 …… 第二个线程
MyThreadWork2 开始启动…… 第三个线程,100
MyThreadWork2 开始启动…… 第四个线程,2
运行结束…… 第一个线程
运行结束…… 第二个线程
运行结束…… 第三个线程,101
运行结束…… 第四个线程,3
光从代码看,我们的输出 MyState 信息的代码应该是后面执行,想不到它居然在线程启动之前就执行了!
呵呵,这就是多线程!
看样子,我需要控制我的主线程——等所有的线程池中的线程都执行完成后,才接着执行主线程中输出 MyState 信息的代码。