我的程序有主窗口形式。我要把一个漫长的任务放在不同的线程中。我还有另一个小表格(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
由于它处于不同线程中,因此不确定是否需要他们查看,但我正在向他们显示:
InitGrid:
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