线程池
当应用程序需要执行长时间运行的本地进程(例如很长的计算、文件处理或初始化)时,可以利用 .net Framework 精简版提供的内置线程池。线程池允许在后台运行多个工作,而不需要为每个任务频繁地创建和销毁单独的线程,从而减少了开销。
.NET Framework 精简版线程池通过 ThreadPool 类提供。通过将一个方法打包到 WaitCallback 委托中,然后将该委托传递给 ThreadPool.QueueUserWorkItem 静态方法,在线程池中对任务进行排队。
在上面的示例中,ReadBigFile 方法将在线程池中排队并在一个可用的线程上运行。对 QueueUserWorkItem 的调用将中断,直到将请求放入队列中。
当要向后台进程传递参数时,QueueUserWorkItem 将提供一个重载,该重载接受一个附加参数,然后将其传递给已排队的方法。该参数被定义为对象,因而可以传递任何类型的参数。
显式创建的线程
有些情况下,后台进程(例如连续读取全球定位系统或监视设备)会占用应用程序的大部分运行时间。在这些情况下,最好为特定的任务创建专用的线程。
专用线程通过 Thread 类的实例实现,并通过将方法包装到 ThreadStart 委托,将此委托传递给 Thread 类构造函数,然后调用 Thread.Start 方法来创建。
在本例中,ReadGPSFeed 方法运行在一个新创建的线程上。此线程专用于 ReadGPSFeed 方法,并在该方法退出后终止。
通过专用线程完成的工作通常是以某种循环的方式执行处理。尽管在有些情况下由后台进程本身确定处理是否完成,但更多的情况下是由某个外部事件(如用户请求或应用程序关闭)来确定。以信号方式通知后台线程终止的最简单方式是通过类级别的布尔标志,如以下代码所示:
在本例中,btnStartGPS_Click 通过将标志设置为“true”并启动相关线程,以启动后台处理。ReadGPSFeed 方法继续处理,直到通过 btnStopGPS_Click 将 _continueGPSRead 标志设置为“false”为止。
当应用程序需要执行长时间运行的本地进程(例如很长的计算、文件处理或初始化)时,可以利用 .net Framework 精简版提供的内置线程池。线程池允许在后台运行多个工作,而不需要为每个任务频繁地创建和销毁单独的线程,从而减少了开销。
.NET Framework 精简版线程池通过 ThreadPool 类提供。通过将一个方法打包到 WaitCallback 委托中,然后将该委托传递给 ThreadPool.QueueUserWorkItem 静态方法,在线程池中对任务进行排队。
void ReadBigFile(object val) { // 执行读取和处理文件的操作 } public void btnStartRead_Click(object sender, EventArgs e) { // 将 ReadBigFile 打包到委托中并提交给线程池 WaitCallback w = new WaitCallback(ReadBigFile) ; ThreadPool.QueueUserWorkItem(w) ; } |
在上面的示例中,ReadBigFile 方法将在线程池中排队并在一个可用的线程上运行。对 QueueUserWorkItem 的调用将中断,直到将请求放入队列中。
当要向后台进程传递参数时,QueueUserWorkItem 将提供一个重载,该重载接受一个附加参数,然后将其传递给已排队的方法。该参数被定义为对象,因而可以传递任何类型的参数。
void ReadBigFile2(object val) { string dataFile = (string) val ; // val 是对 fName 的引用 // 执行读取和处理 dataFile 的操作 } public void btnStartRead_Click(object sender, EventArgs e) { string fName = "BigDataFile.xml" ; WaitCallback w = new WaitCallback(ReadBigFile2) ; // fName 将被传递给 ReadBigFile ThreadPool.QueueUserWorkItem(w, fName) ; } |
显式创建的线程
有些情况下,后台进程(例如连续读取全球定位系统或监视设备)会占用应用程序的大部分运行时间。在这些情况下,最好为特定的任务创建专用的线程。
专用线程通过 Thread 类的实例实现,并通过将方法包装到 ThreadStart 委托,将此委托传递给 Thread 类构造函数,然后调用 Thread.Start 方法来创建。
void ReadGPSFeed() { // 循环读取 GPS 数据 } public void btnStartGPS_Click(object sender, EventArgs e) { ThreadStart startMethod = new ThreadStart(ReadGPSFeed); Thread gpsThread = new Thread(startMethod); gpsThread.Start(); // 启动后台线程 } |
在本例中,ReadGPSFeed 方法运行在一个新创建的线程上。此线程专用于 ReadGPSFeed 方法,并在该方法退出后终止。
通过专用线程完成的工作通常是以某种循环的方式执行处理。尽管在有些情况下由后台进程本身确定处理是否完成,但更多的情况下是由某个外部事件(如用户请求或应用程序关闭)来确定。以信号方式通知后台线程终止的最简单方式是通过类级别的布尔标志,如以下代码所示:
Class MyForm : Form { // 为清楚起见,省略了部分类成员 private bool _continueGPSRead = false; // 读取控制标志 void ReadGPSFeed() { while (_continueGPSRead) // 循环,直到为 false { // 读取 GPS 数据 } } public void btnStartGPS_Click(object sender, EventArgs e) { ThreadStart startMethod = new ThreadStart(ReadGPSFeed); Thread gpsThread = new Thread(startMethod); _continueGPSRead = true; // 设置循环标志 gpsThread.Start(); // 启动后台线程 } public void btnStopGPS_Click(object sender, EventArgs e) { _continueGPSRead = false ; // 发送 ReadGPSFeed 信号以终止 } } |
在本例中,btnStartGPS_Click 通过将标志设置为“true”并启动相关线程,以启动后台处理。ReadGPSFeed 方法继续处理,直到通过 btnStopGPS_Click 将 _continueGPSRead 标志设置为“false”为止。