Vb.net 从非主线程调用API导致缺少接口错误

Vb.net 从非主线程调用API导致缺少接口错误,vb.net,multithreading,winapi,com,Vb.net,Multithreading,Winapi,Com,我在应用程序中使用系统映像列表,如下所述。从主线程调用此函数非常有效,但是,如果我尝试从其他线程调用此函数,它会导致错误,原因我不太明白 系统映像列表界面为: <ComImportAttribute(), GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _ Private Interface iIm

我在应用程序中使用系统映像列表,如下所述。从主线程调用此函数非常有效,但是,如果我尝试从其他线程调用此函数,它会导致错误,原因我不太明白

系统映像列表界面为:

 <ComImportAttribute(), GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Private Interface iImageList
    <PreserveSig> _
    Function Add(ByVal hbmImage As IntPtr, ByVal hbmMask As IntPtr, ByRef pi As Integer) As Integer

'here comes the rest of standard functions for this interface

End Interface
如果从非主线程调用(仅从标准.Net后台工作线程调用),则创建列表的最后一次调用会导致以下错误:

无法将“System.\u ComObject”类型的COM对象强制转换为接口类型“iImageList”。此操作失败,因为对IID为“{46EB5926-582E-4017-9FDF-E8998DAA0950}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT的异常:0x80004002(E_NOINTERFACE))

我想了解为什么会发生这种情况,为什么在不同的线程中创建接口时,
iImageList
接口突然变得不受支持(它可以从主线程完美地工作),以及是否有办法解决这个问题

附言


我确实读过类似的问题,但我并没有跨线程传递信息(我试图从一个线程创建和使用Imagelist),我也不知道如何解决这个问题。使用STA\MTA线程属性没有给出任何结果。最后,我应该说我对COM业务知之甚少。

我想我误解了。我以为您是说在一个线程中调用了
SHGetImageList
,但在另一个线程中通过生成的接口指针调用了它。我很确定必须从STA线程调用
SHGetImageList
,但不管是哪个STA线程;只要工作线程加入STA,它就应该从该线程开始工作。为什么要按顺序导入
SHGetImageList()
?MSDN没有记录任何要使用的特定序号。此函数(与许多SHxxx函数一样)可能会秘密创建COM对象。这些对象可能被缓存(因为有一个关联的
fileiconit
函数可以“重新初始化”事物)。如果发生这种情况,他们可能会被调到另一种类型的公寓,而这正是引起E_NOINTERFACE的典型原因。在使用shell函数时,我认为最好使所有线程都是STA(以SHGetFileInfo注释为例)。不明显的细节是,图标可以由生成。这样的扩展从插件架构中得到了很好的保证,它们不必是线程安全的。问题是,BackgroundWorker使用的线程总是在MTA中,简而言之就是“对线程不安全的组件不提供帮助”。IImageList没有代理/存根。回退不存在,也没有实现IMarshal,这就是错误消息的真正含义。也许这是可行的,但您仍然无法使用返回的接口。它不是线程安全的。所有代码都必须在STA线程上运行,不仅包括SHGetImageList(),还包括使用该接口的代码。您必须遵守STA合同,调用Application.Run()不是可选的。STA线程的示例。或者停止与机器的战斗,这个函数是在你的UI线程上运行的,所以从那里开始使用它。
  <DllImport("shell32.dll", EntryPoint:="#727")> _
Private Shared Function SHGetImageList(ByVal iImageList As Integer, ByRef riid As Guid, ByRef ppv As IImageList) As Integer
End Function
Dim ID As New Guid("46EB5926-582E-4017-9FDF-E8998DAA0950")
Dim Intrf As iImageList=Nothing
Dim extraLargeIcons = &H2
Dim Ret As Integer = SHGetImageList(CInt(Fix(extraLargeIcons)), ID, Intrf )