我有一个具有长时间运行的Active Directory查询的程序。我想利用VB.NET的Async技术,但当我将我的函数转换为Async时,我开始得到一个InvalidCastException。当我切换回来时,错误消失了。为什么Async会导致我的COM对象出现InvalidCastException?
异常消息:
无法将“System .__ ComObject”类型的COM对象强制转换为接口类型“IDirectorySearch”。此操作失败,因为对IID为“{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE))
这必须发生在核心库中的某个地方,因为我的代码中没有对IDirectorySearch的任何引用。实际上,堆栈跟踪并不是很有启发性:
这是抛出异常的地方(根据调试器):
Private Overloads Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
这是实际的代码。我创建了两个版本来演示代码之前(FindAll1)和之后(FindAll2)异步:
Private Async Sub FindAllButton_Click(sender As Object, e As RoutedEventArgs) Handles FindAllButton.Click
'Me.Entries = Await FindAll1(Me.FilterText) ' Works
Me.Entries = Await FindAll2(Me.FilterText) ' Doesn't Work
End Sub
Private Async Function FindAll1(filterText As String) As Task(Of IEnumerable(Of DirectoryEntryWrapper))
Dim l_searcher As New DirectorySearcher()
l_searcher.SizeLimit = Me.QuerySizeLimit
l_searcher.Filter = filterText
Me.IsLoading = True
Dim l_results =
From result In l_searcher.FindAll().Cast(Of SearchResult)()
Select entry =
New DirectoryEntryWrapper(result.GetDirectoryEntry(), AddressOf DirectoryEntryWrapperEventHandler)
Order By entry.Name
Me.IsLoading = False
Return l_results
End Function
Private Async Function FindAll2(filterText As String) As Task(Of IEnumerable(Of DirectoryEntryWrapper))
Dim l_searcher As New DirectorySearcher()
l_searcher.SizeLimit = Me.QuerySizeLimit
l_searcher.Filter = filterText
Me.IsLoading = True
Dim l_results =
Await Task.Run(
Function() _
From result In l_searcher.FindAll().Cast(Of SearchResult)()
Select entry =
New DirectoryEntryWrapper(result.GetDirectoryEntry(), AddressOf DirectoryEntryWrapperEventHandler)
Order By entry.Name
)
Me.IsLoading = False
Return l_results
End Function