vb.net - 使用 BackgroundWorker 通过 FileSystemWatcher 更新主窗体 UI?
问题描述
我在尝试使用 BackgroundWorker 来更新我的主表单 UI 以响应 FileSystemWatcher 事件被触发时有点卡住了。
- FileSystemWatcher 检查添加到特定文件夹的图像,触发 OnCreated Handler
- OnCreated 处理程序调用 RunWorkerAsync(e.FullPath) 将文件名传递给后台工作者
- 后台工作者 RunWorkerAsync 获取文件路径,并将项目添加到 List(Of Product)
- List(Of Product) 被添加到主 UI 上的 ListBox 控件
我的第一个问题是在后台工作人员完成后更新主 UI 线程。我在后台工作人员中处理图像,因为从图像生成缩略图需要几秒钟,并且不想锁定 UI。
我遇到的第二个问题是在我的事件第二次触发之后,并且抛出异常表明后台工作人员很忙。
Private HoldingTank As New List(Of Product)
Private Sub LoadImages()
Me.ToolStripStatusLabelUpdate.Text = "Images Loading - Please Wait...."
CheckedListBoxView.Items.Clear()
HoldingTank = Me.CreateImageList()
For Each product As Product In HoldingTank
Me.CheckedListBoxView.Items.Add(New ListViewDataItem With {.Image = product.Image, .ImageAlignment = ContentAlignment.MiddleCenter, .Tag = product})
Next
Me.ToolStripStatusLabelUpdate.Text = "Ready"
End Sub
Public Sub WatchFolders()
watcher.Path = PathImport
watcher.Filter = "*.tif"
AddHandler watcher.Created, AddressOf OnCreated
watcher.EnableRaisingEvents = True
End Sub
Sub OnCreated(sender As Object, e As IO.FileSystemEventArgs)
BackgroundWorker1.RunWorkerAsync(e.FullPath)
End Sub
Private Sub BackgroundWorker1_LoadImages(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
HoldingTank.Add(New Product() With {.FileName = path.getFileName(e.argument), .FileExtension = path.GetExtension(e.argument), .FileFullPath = e.argument, .Image = GenerateThumbnail(e.argument)})
'// Function GenerateThumbnail returns an Image object
End Sub
- 一旦 BackgroundWorker 将项目添加到列表中,我如何更新 CheckedListBoxView 控件而不会获得非法的跨线程调用?
- 如果在工作人员完成之前引发另一个文件事件,我如何检查工作人员是否忙?
解决方案
首先,确保您已设置SynchronizingObject
. FileSystemwatcher
如果您没有,它将在辅助线程上引发其事件,在这种情况下您不希望这样做。您应该将表单分配给该属性。
其次,您不要触摸DoWork
事件处理程序中的 UI 或从中调用的任何方法。这都是在辅助线程上执行的,除了 UI 线程之外,您不能在任何地方修改 UI。您可以在DoWork
事件处理程序中完成所有工作,然后将结果数据分配给e.Result
属性。
然后处理在RunWorkerCompleted
UI 线程上执行的事件,从属性中取回该数据e.Result
,然后更新 UI。我不确切知道您在那里使用的是什么控件,但您应该能够在辅助线程上创建项目,但是您需要将它们添加到 UI 线程上的控件中。
你可以在这里BackgroundWorker
找到我自己的例子。
推荐阅读
- mule - 获取数组中对象值的总和
- kubernetes - Kubernetes Service 没有活动的 Endpoint
- linux - 删除使用 add-apt-repository 添加的存储库
- sling - 在部署之前更改 Apache sling 默认用户名/密码
- javascript - 拖放文件上传触发器两次
- angular - 多个可拖动的模态或角度弹出窗口
- javascript - 如何在纯JS中滚动动画rotateX?
- node.js - Amazon SP-API 不能扮演我自己的角色?
- wordpress - WordPress Elementor 形式的确认电子邮件
- angular - 角度输入绑定性能