创建显示的窗体
最后,我们可以创建窗体,将其用于启动或取消后台进程。该窗体还将显示活动和状态信息。
打开 Form1 的设计器并添加两个按钮(btnStart 和 btnRequestCancel)、两个标签(Label1 和 Label2)、一个 ProgressBar (ProgressBar1) 和一个 ActivityBar (ActivityBar1),如图 7 所示。
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com)图 7:Form1 控件的布局
该窗体需要实现 IClient,以便 Controller 对象与之交互:
Imports Background
Public Class Form1 Inherits System.Windows.Forms.FormImplements IClient
该窗体还需要 Controller 对象和一个标志,用以跟踪后台操作是处于活动状态还是处于完成状态。
Private mController As New Controller(Me) Private mActive As Boolean
然后,我们可以添加方法,以实现由 IClient 定义的接口。建议将这些方法放在 Region 中,以表示它们实现的是辅助接口:
#Region " IClient " Private Sub TaskStarted(ByVal Controller As Controller) _ Implements IClient.Start mActive = True Label1.Text = "Starting" Label2.Text = "0%" ProgressBar1.Value = 0 ActivityBar1.Start() End Sub Private Sub TaskStatus(ByVal Text As String) _ Implements IClient.Display Label1.Text = Text Label2.Text = CStr(mController.Percent) & "%" ProgressBar1.Value = mController.Percent End Sub Private Sub TaskFailed(ByVal e As Exception) _ Implements IClient.Failed ActivityBar1.Stop() Label1.Text = e.Message MsgBox(e.ToString) mActive = False End Sub Private Sub TaskCompleted(ByVal Cancelled As Boolean) _ Implements IClient.Completed Label1.Text = "Completed" Label2.Text = CStr(mController.Percent) & "%" ProgressBar1.Value = mController.Percent ActivityBar1.Stop() mActive = False End Sub#End Region
请注意,这一段代码中的所有内容均与线程无关,其中的每一部分代码都可以在我们得知后台操作的状态时做出相应的响应。每次响应后,我们都会更新显示以表明进程的状态和完成百分比(以文字的形式或通过 ProgressBar 显示),并启动和停止 ActivityBar 控件。
mActive 标志非常重要。如果用户在辅助线程处于活动状态时关闭窗体,应用程序可能会挂起或变得不稳定。要防止出现这种情况,我们可以打断窗体的 Closing 事件并取消关闭尝试(如果后台进程处于活动状态)。
Private Sub Form1_Closing(ByVal sender As Object, _ ByVal e As System.ComponentModel.CancelEventArgs) _ Handles MyBase.Closing e.Cancel = mActive End Sub
我们还可以选择在这种情况下初始化取消操作,但是这取决于特定的应用程序要求。
其余的代码都是为了实现按钮的 Click 事件。
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com)Private Sub btnStart_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStart.Click mController.Start(New Worker(2000000, 100)) End Sub Private Sub btnStop_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStop.Click Label1.Text = "Cancelling ..." mController.Cancel() End Sub
Start(开始)按钮只调用 Controller 对象的 Start 方法,并将 Worker 对象的实例传递给它。
您可能需要调整用于初始化 Worker 对象的值,以便在您的计算机上获得所需的结果。这些特定的值提供了双处理器 P3/450 计算机上的一个良好示例。显然,这只是用于测试目的。真正的 Worker 对象将实现更有意义、运行时间更长的进程。
Cancel(取消)按钮将调用 Controller 对象的 Cancel 方法,同时还会更新显示,以表明已请求取消。请记住,这只是一个取消“请求”,在辅助线程真正停止运行之前可能需要等待一些时间。最好能够为用户提供即时反馈,至少应让用户知道系统已经注意到用户的单击按钮操作。
现在,我们可以运行应用程序了。单击 Start(开始)按钮时,Worker 就应该开始运行,而且显示的内容会在运行时更新。您可以将窗体移动到屏幕上的任意位置,也可以与其交互,因为 UI 线程本质上还处于空闲状态,可以随时与您交互。
同时,辅助线程在后台进