vb.net - 后台任务表单未按预期工作并冻结 GUI
问题描述
我有我的程序的主窗口形式。我想把一个很长的任务放到不同的线程中。我有另一个小表单(FrmCircularProgress),当该任务运行时,它会在顶部显示给用户,这是普通的简单表单,其中没有任何内容。问题是当长任务正在运行并且我的等待表单出现(FrmCircularProgress)时,它似乎没有响应(冻结),因为例如在此过程中我无法移动它。我不知道为什么因为任务在不同的线程等待表单上运行应该是响应式的。请多多支持。
请注意,有趣的是,我在许多其他地方使用完全相同的方法 - 使用这个 _pic.Shown,AddressOf XXX,其中 XXX 的内部方法我放置了我想放在不同线程上的代码,所有工作都意味着 FrmCircularProgress 是响应式的。这是第一次发生,我不知道它的原因。
在主表单类之上:
Private WithEvents _pic As FrmCircularProgress
Private _tsk As Task(Of Boolean)
Button handler where long running task is raised:
Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
Try
_pic = New FrmCircularProgress(eCircularProgressType.Donut)
AddHandler _pic.Shown, AddressOf DoTheJob
_pic.ShowDialog()
Catch ex As Exception
Finally
RemoveHandler _pic.Shown, AddressOf DoTheJob
End Try
End Sub
任务本身:
Public Sub DoTheJob(sender As Object, e As EventArgs)
_tsk = Task.Run(Function()
'--Run lenghty task
Dim resu = False
Try
InitGrid()
resu = True
Catch ex As Exception
_pic.Invoke(New Action(Sub() MessageBoxEx.Show(_pic, ex.ToString())
Finally
'--Close form once done (on GUI thread)
_pic.Invoke(New Action(Sub() _pic.Close()))
End Try
Return resu
End Function)
End Sub
由于它位于不同的线程中,因此不确定您是否需要它们查看,但我正在向它们展示:
初始化网格:
Public Sub InitGrid() Handles _editDictionaryForm.Updated, _addDictionaryForm.Updated
If InvokeRequired Then
Invoke(New MethodInvoker(AddressOf InitGrid))
Else
Try
BindArticlesData()
InitializeGridBasiscSettings()
Catch ex As Exception
End Try
End If
End Sub
Private Sub BindArticlesData()
If InvokeRequired Then
Invoke(New MethodInvoker(AddressOf BindArticlesData))
Else
Try
RemoveHandler gridDic.DataBindingComplete, AddressOf SuperGridControl1DataBindingComplete
AddHandler gridDic.DataBindingComplete, AddressOf SuperGridControl1DataBindingComplete
gridDic.PrimaryGrid.DataSource = Nothing
Dim dada = CInt(DirectCast(cbLang.SelectedItem, DataRowView).Item("Id"))
gridDic.PrimaryGrid.DataSource = _dictionary.GetDataSet(dada, txtFilterDE.Text)
Catch ex As Exception
End Try
End If
End Sub
Private Sub InitializeGridBasiscSettings()
If InvokeRequired Then
Invoke(New MethodInvoker(AddressOf InitializeGridBasiscSettings))
Else
//simple grid layout adjustments
End If
End Sub
到目前为止我做了什么:
因为到目前为止我意识到在从不同线程处理时使用invoke()是正确的,但它仍然阻塞主线程,因此我认为扩展变量数据可能很好,将其填充到Invoke中,但是将数据设置到网格的数据源之外调用以不阻止 GUI。尽管如此,由于某种原因,问题似乎仍然相同。
Private Sub BindArticlesData()
Dim data As DataSet ' <=======put outside Invoke
Invoke(Sub()
RemoveHandler gridDic.DataBindingComplete, AddressOf SuperGridControl1DataBindingComplete
AddHandler gridDic.DataBindingComplete, AddressOf SuperGridControl1DataBindingComplete
gridDic.PrimaryGrid.DataSource = Nothing
Dim dada = CInt(DirectCast(cbLang.SelectedItem, DataRowView).Item("Id"))
data = _dictionary.GetDataSet(dada, txtFilterDE.Text)
End Sub)
gridDic.PrimaryGrid.DataSource = data 'fill outside Invoke the result
End Sub
编辑进一步讨论:
Private Sub BindArticlesData()
Dim data As DataSet
RemoveHandler gridDic.DataBindingComplete, AddressOf SuperGridControl1DataBindingComplete
AddHandler gridDic.DataBindingComplete, AddressOf SuperGridControl1DataBindingComplete
gridDic.PrimaryGrid.DataSource = Nothing
Invoke(Sub()
Dim dada = CInt(DirectCast(cbLang.SelectedItem, DataRowView).Item("Id"))
data = _dictionary.GetDataSet(dada, txtFilterDE.Text)
End Sub)
gridDic.PrimaryGrid.DataSource = data
End Sub
解决方案
推荐阅读
- java - Java Scanner/Input Help(输入不匹配异常)
- mysql - 如何获取另一个表的行数,使用 SELECT 列作为使用 MySQL 的 WHERE 子句
- python - 扩展numpy数组维度以满足不同需求的最佳方法
- c++ - 是否有工具可以识别一组 C++ 源文件引用的外部标识符?
- java - Mozilla FireFox(无响应)- Selenium WebDriver 拒绝通过 driver.quit() 命令死机
- java - 方法 add(ArrayList
) 在 ArrayList 类型中 > 不适用于参数(无效) - python-3.x - 防止python3脚本在操作完成之前用ctrl c终止
- javascript - 将图像幻灯片添加到页面
- c# - 如何在 C# 中枚举类型的每个枚举值上添加元数据信息?
- git - 当审查分支合并时,Gitlab CI 自动 rebase 主分支