Rockford Lhotka
Magenic Technologies
2002年10月1日
从 MSDN Code Center
下载 VBbackground.exe 示例文件(英文)。
http://msdn.microsoft.com/code/default.asp?url=/code/sample.
asp?url=/msdn-files/026/002/886/msdncompositedoc.xml
(请注意,在示例文件中,
程序员的注释使用的是英文,本文中将其译为中文是为了便于读者进行理解。)
摘要:Rocky Lhotka 建议并实现了一个结构化架构示例,该架构可用于充当辅助线程和 UI 线程之间的媒介,从而简化编写多线程辅助代码和 UI 以对其进行控制的过程。该架构包括可
下载的代码示例,可以根据您的应用需要进行调整。
使用多线程,可以使应用
程序同时执行多项任务。使用多线程,可以让一个线程运行用户界面,让另一个线程进行复杂运算或在后台操作。由于 Microsoft® Visual Basic® .NET 支持多线程,因此我们很容易获得此功能。
但多线程也有其不足之处。当应用
程序使用多个线程时,我们总会遇到这样的问题:多个线程同时尝试与相同的数据或资源进行交互。出现这种情况时,
问题就会变得非常复杂并且难以调试。
更糟糕的是,多线程代码通常在最初开发期间似乎运行正常,但在生产过程中则会因为出现意外的情况(多个线程同时与相同的数据或资源进行交互)而导致失败。这样就增大了多线程编程的危险性!
由于设计和调试多线程应用
程序非常困难,因此 Microsoft 在 COM 中创建了“单线程单元”(STA) 概念。Visual Basic 6 代码始终在 STA 中运行,因而代码只需考虑单线程即可。这样即可彻底避免共享数据或资源所带来的问题,但是同时也意味着,我们必须采取严格的措施才能利用多线程的优势。
.NET 中不会出现 STA 中的这种常见问题。所有 .NET 代码都在允许多线程操作的 AppDomain 中运行。这意味着 Visual Basic .NET 代码也在 AppDomain 中运行,因此可以使用多线程操作。显然,任何时候进行此操作都必须小心编写代码,以避免线程之间的冲突。
要避免线程之间发生冲突,最简单的方法就是确保多个线程永远不会与相同的数据或资源进行交互。尽管不太可能,但是对于任何多线程应用
程序来说,应该在设计时尽量避免使用或尽量少使用共享数据或共享资源。
这样不仅能简化编码和调试过程,还能提高性能。要解决线程之间的冲突,必须使用能够在某个线程完成操作之前阻止或暂停其他线程的同步技术。阻止线程也就是使线程处于空闲状态,不进行任何操作,因此会降低性能。
取消按钮和状态显示
在应用
程序中使用多线程的原因有多种,但最常见的原因是我们一方面需要执行一个长时间运行的任务,另一方面又希望某些或所有用户界面对用户来说始终处于响应状态。
至少我们应该使 Cancel(取消)按钮始终保持响应状态,使用户能够通过它告诉系统,他们希望终止长时间运行的任务。
在 Visual Basic 6 中,我们尝试使用 DoEvents、计时器控件和许多其他方法进行该操作。Visual Basic .NET 中的操作则简单得多,因为我们可以使用多线程。而且,只要我们小心谨慎,就可以完成此操作且不会使代码或调试复杂化。
要在多线程环境中成功实现 Cancel(取消)按钮,关键是要记住 Cancel(按钮)的作用只是“请求”取消任务。由后台任务决定何时停止。
如果我们实现一个能够直接停止后台进程的 Cancel(取消)按钮,则可能会在执行某些敏感性操作的过程中将其停止,或者在后台进程关闭重要资源(例如,文件处理程序或数据库连接)之前将其停止。而这有可能导致严重后果,引起死机、应用程序行为不稳定或应用
程序完全崩溃。
因此,Cancel(取消)按钮的作用应该只是请求停止后台任务。后台任务可以检查某一时间点上是否存在取消操作的请求。如果检测到取消操作的请求,后台线程则可