backThread.Start()
为了建立该线程,我们传递了Worker 对象的IWorker
的接口的Start方法的地址。接着我们简单地调用了线程对象的Start方法开始该处理。在这儿我们必须仔细,保证既没有UI与Worker直接交互,也没有Worker与UI直接交互。
注意"取消"方法只是设置了一个标志用于显示我们想工作不再运行。直到工作代码周期性查看是否该停止运行。
现在我们实现在Worker对象运行时将被工作线程调用的代码。该代码有趣一些,它将工作线程调用的Display和Completed方法传递到UI,但却在UI线程上。
为了实现它,我们使用窗体对象的Invoke方法。Invoke方法接受指向该窗体将调用的方法的委托,同时有一个含有该方法的参数的类型对象数组。
Invoke方法不能直接调用窗体的方法。它请求窗体转向并使用该窗体的UI线程来调用方法。这通过发送一个Windows消息给窗体在后台实现。这意味着窗体获取这些方法调用与它从操作系统本身获取click或
keypress事件非常相象。
典型情况下这些并不麻烦。其结果是Invoke方法触发一个进程,通过该进程窗体终止在自己的UI线程上运行的方法,这正是我们的设计目标。
同样这些代码写入一个区域(Region),可以使它们在worker线程中被调用时比较清晰。
'从worker线程调用来更新显示
'它用状态信息触发了一个向UI的方法调用
'该调用在UI线程上作出
Private Sub Display(ByVal Text As String) _
Implements IController.Display
Dim disp As New DisplayDelegate( _
AddressOf CType(mClient, IClient).Display)
Dim ar() As Object = {Text}
'调用UI线程的客户窗体来更新显示
mClient.BeginInvoke(disp, ar)
End Sub
'从worker线程调用用于显示失败。
'它用exception对象触发了一个向UI的方法调用
'该调用在UI线程上作出
Private Sub Failed(ByVal e As Exception) _
Implements IController.Failed
Dim disp As New FailedDelegate(_
AddressOf CType(mClient, IClient).Failed)
Dim ar() As Object = {e}
'调用UI线程上的客户窗体来显示失败
mClient.Invoke(disp, ar)
End Sub
'从worker线程调用来表明完成百分比
'该值进入Controller,如果需要能在那儿被UI读取
Private Sub SetPercent(ByVal Percent As Integer) _
Implements IController.SetPercent
mPercent = Percent
End Sub
'从worker线程调用来显示已经完成
'传递了一个参数用于显示真的完成了和者"取消"了
'该调用在UI线程中作出
Private Sub Completed(ByVal Cancelled As Boolean) _
Implements IController.Completed
mRunning = False
Dim comp As New CompletedDelegate( _
AddressOf CType(mClient, IClient).Completed)
Dim ar() As Object = {Cancelled}
'从UI线程调用客户窗体来显示完成了
mClient.Invoke(comp, ar)
End Sub
'显示是否仍在运行或者有"取消"请求
'该调用在worker线程上作出,这样worker代码可以看是否应该温和地退出
Private ReadOnly Property Running() As Boolean _
Implements IController.Running
Get
Return mRunning
End Get
End Property
#End Region
Failed和Completed方法使用了窗体的Invoke方法。下面使Failed的代码:
Dim disp As New FailedDelegate(_
AddressOf CType(mClient, IClient).Failed)
Dim ar() As Object = {e}
'从UI线程调用客户窗体来显示失败
mClient.Invoke(disp, ar)
首先所我们从IClient接口中建立一个委托指向窗体的Failed事件,接着我们声明了一个类型对象数组存放传递给该方法的参数值,最后调用客户窗体的Invoke方法,传递委托指针和参数数组给窗体。
随后窗体在UI线程中使用这些参数调用该方法,它可以安全的运行来更新显示。
这整个过程是同步的,意味着向窗体作调用时工作线程被阻塞。虽然因为错误消息或者完成消息而阻塞工作线程是合适的,但我们不想因为一点点状态显示而阻塞它。
为了避免在状态显示时的阻塞,Display方法用BeginInvoke代替了Invoke.
BeginInvoke促成窗体上的方法调用异步完成,这样工作线程能保持运行而不需要等待窗体显示方法的完成。
AddressOf CType(mClient, IClient).Display)
Dim ar() As Object = {Text}
'调用UI线程上的客户窗体来更新显示
mClient.BeginInvoke(disp, ar)
在这种情况下使用BeginInvoke通过避免阻塞保持了工作线程尽可能地高效率运行。
最后我们建立ActivityBar控件来显示动态点。
给项目添加一个叫ActivityBar的用户控件,将该控件调整到大约宽110,高20,可以拖拉边界或在属性窗口中设定Size值来实现。
其它的在代码中实现。为了建立一系列动态闪烁的"亮点",我们将Timer控件与一组PictureBox控件一起使用。每次Timer控件到期,我们将下一个PictureBox设为绿色,将已经是绿色的变成窗体色。
放置Timer控件,将它的名字改为tmAnim,Interval属性设为300。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



