多线程应用程序
更新:2007 年 11 月
使用 Visual Basic 可以编写同时执行多项任务的应用程序。有潜力支持其他一些任务的任务能够在不同的线程上执行,这种进程被称为“多线程处理”或“自由线程处理”。
使用多线程处理的应用程序对用户输入的响应能力更强,因为大量占用处理器的任务在不同的线程上执行时,用户接口是活动的。多线程处理在创建可缩放应用程序时也很有用,因为工作量增加时可以添加线程。
使用 BackgroundWorker 组件
创建多线程处理应用程序的最可靠方法是使用 BackgroundWorker 组件。此类管理一个专用于处理您指定的方法的单独线程。有关示例,请参见演练:多线程处理。
若要在后台开始一项操作,请创建 BackgroundWorker,并侦听报告操作进度和在操作完成时发出信号的事件。可以通过编程方式创建 BackgroundWorker 对象,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在“窗体设计器”中创建 BackgroundWorker,则它会出现在“组件栏”中,而且它的属性会显示在“属性”窗口中。
为后台操作做好准备
若要为后台操作做好准备,请添加 DoWork 事件的事件处理程序。在此事件处理程序中调用耗时的操作。
若要开始此操作,请调用 RunWorkerAsync。若要收到进度更新的通知,请处理 ProgressChanged 事件。若要在操作完成时收到通知,请处理 RunWorkerCompleted 事件。
处理 ProgressChanged 和 RunWorkerCompleted 事件的方法可以访问应用程序的用户界面,原因是这两个事件是在调用了 RunWorkerAsync 方法的线程上引发的。但是,DoWork 事件处理程序无法使用任何用户界面对象,因为它在后台线程上运行。
创建和使用线程
如果需要对应用程序的线程的行为进行更多的控制,则可以自己管理线程。但请注意,编写正确的多线程应用程序可能很困难:应用程序可能会因为争用条件而停止响应或遇到瞬态错误。有关更多信息,请参见 线程安全组件。
在 Visual Basic 中创建新线程,方法是声明 Thread 类型的变量并以 AddressOf 语句及要在新线程上执行的过程或方法的名称来调用构造函数。以下代码提供了一个示例:
Dim TestThread As New System.Threading.Thread(AddressOf TestSub)
启动和停止线程
若要开始执行新线程,可使用 Start 方法,如以下代码所示:
TestThread.Start()
若要停止执行线程,可使用 Abort 方法,如以下代码所示:
TestThread.Abort()
除启动和停止线程之外,还可以通过调用 Sleep 或 Suspend 方法暂停线程,用 Resume 方法继续挂起的线程,用 Abort 方法销毁线程,如以下代码所示:
TestThread.Sleep(1000)
TestThread.Abort()
线程方法
下表显示了一些可用于控制单个线程的方法。
方法 |
操作 |
---|---|
使线程开始运行。 |
|
使线程暂停指定的一段时间。 |
|
在线程到达安全点时,使其暂停。 |
|
在线程到达安全点时,使其停止。 |
|
重新启动挂起的线程 |
|
使当前线程一直等到另一线程完成。在与超时值一起使用时,如果该线程在分配的时间内完成,此方法将返回 True。 |
安全点
这些方法大多数都一目了然,但安全点对您可能是个新概念。安全点是指代码中公共语言运行库可以安全地执行自动“垃圾回收”的位置。垃圾回收是指释放不再使用的变量并回收内存的过程。调用线程的 Abort 或 Suspend 方法时,公共语言运行库将对代码进行分析,确定让线程停止运行的适当位置。
线程属性
线程也包含许多有用的属性,如下表所示:
属性 |
值 |
---|---|
如果线程处于活动状态,则包含值 True。 |
|
获取或设置一个布尔值,该值表示一个线程是否是或是否应当是后台线程。后台线程与前台线程类似,但后台线程不阻止进程停止。一旦某个进程的所有前台线程都停止,公共语言运行库就会对仍处于活动状态的后台线程调用 Abort 方法,从而结束该进程。 |
|
获取或设置线程的名称。通常用于在调试时发现各个线程。 |
|
获取或设置操作系统用于确定线程调度优先顺序的值。 |
|
获取或设置用于特定线程的线程模型。线程模型在线程调用非托管代码时很重要。 |
|
包含描述线程状态的值。 |
有关线程状态和方法的更多信息,请参见线程状态。
线程优先级
每个线程都有一个优先级属性,用于确定其执行所占用的处理器时间片大小。操作系统为高优先级线程分配较长的时间段,并为低优先级线程分配较短的时间段。新创建的线程具有值 Normal,但您可以将 Priority 属性更改为 ThreadPriority 枚举中的任何值。
有关各种线程优先级的详细说明,请参见 ThreadPriority。
前台和后台线程
前台线程的运行时间不限定,而后台线程则在最后一个前台线程停止时立即停止。可以使用 IsBackground 属性确定或更改线程的后台状态。