我正在尝试利用异步/等待模式,使用 HttpClient post 请求的结果填充列表框。 该应用程序是 Excel VSTO。 该列表框位于 Excel 任务窗格中。 当我尝试填充列表框时收到此错误消息:
System.InvalidOperationException
HResult=0x80131509
Message=Cross-thread operation not valid: Control 'lbo1' accessed from a thread other than the thread it was created on.
Source=SpenHistorianClient
StackTrace:
at SpenHistorianClient.ucEvents.PopulateListBox() in C:\_VSSWorkArea\SPENHistorianClient\SpenHistorianClient\ucEvents.vb:line 410
at SpenHistorianClient.ucEvents.VB$StateMachine_145_btnTagSearch_Click.MoveNext() in C:\_VSSWorkArea\SPENHistorianClient\SpenHistorianClient\ucEvents.vb:line 396
相关代码如下:
Private Async Sub btnTagSearch_Click(sender As Object, e As EventArgs) Handles btnTagSearch.Click
Dim filterText As String = Nothing
Dim itemType As String = Nothing
Dim cnt As Long
Try
_filteredItems = New TagDefinitions
filterText = txtFilter.Text
Await Globals.ThisAddIn.QueryTagList(Globals.ThisAddIn.WebServices(cboSource.SelectedIndex), _filterText, _itemType)
_filteredItems = Globals.ThisAddIn.GetFilteredTagList(filterText)
PopulateListBox()
Catch ex As Exception
Throw
End Try
End Sub
Public Sub PopulateListBox()
Try
For Each item In _filteredItems
_activeLbo.Items.Add(item.TagName)
Next
'Now we have populated the listbox clear the collection as we have no further need of it at this time
_filteredItems.Clear()
Catch ex As Exception
Throw
End Try
End Sub
我没想到会出现跨线程问题,因为类变量 _filteredItems 和列表框都在 TaskPane 中定义,我将其理解为 UI 线程,我读过许多讨论列表框跨线程的帖子代表和后台工作人员的使用,但是我很难将这些知识转移到我的特定环境中。
好吧,最后我成功解决了。 最终得到以下解决方案:
Private Async Sub btnTagSearch_Click(sender As Object, e As EventArgs) Handles btnTagSearch.Click
Dim filterText As String = Nothing
Dim itemType As String = Nothing
Dim cnt As Long
Try
_filteredItems = New TagDefinitions
filterText = txtFilter.Text
Await Globals.ThisAddIn.QueryTagList(Globals.ThisAddIn.WebServices(cboSource.SelectedIndex), _filterText, _itemType)
_filteredItems = Await Globals.ThisAddIn.GetFilteredTagList(filterText)
Invoke(New PopulateListBoxHandler(
AddressOf PopulateListBox))
Catch ex As Exception
Throw
End Try
End Sub
Private Delegate Sub PopulateListBoxHandler()
Public Sub PopulateListBox()
Try
For Each item In _filteredItems
_activeLbo.Items.Add(item.TagName)
Next
'Now we have populated the listbox clear the collection as we have no further need of it at this time
_filteredItems.Clear()
Catch ex As Exception
Throw
End Try
End Sub