C# 在IIS中的第16个托管线程上,从COM库转换到接口失败(InvalidCastException,WinRT起始错误0x80040155)

C# 在IIS中的第16个托管线程上,从COM库转换到接口失败(InvalidCastException,WinRT起始错误0x80040155),c#,com,interop,cassini,ole-automation,C#,Com,Interop,Cassini,Ole Automation,我发布这篇文章的目的主要是为了其他任何关注这个奇怪问题的人,如果有人能解释为什么IIS/Cassini是个魔鬼的话 在大多数情况下,我们可以成功地将ODL中定义的分派对象强制转换为 [ uuid(GUID_FOO) ] dispinterface IFooDisp { ... properties & methods. }; [ uuid(GUID_FOO_COCLASS),noncreatable ] coclass FooDisp { [default] dispin

我发布这篇文章的目的主要是为了其他任何关注这个奇怪问题的人,如果有人能解释为什么IIS/Cassini是个魔鬼的话

在大多数情况下,我们可以成功地将ODL中定义的分派对象强制转换为

[ uuid(GUID_FOO) ]
dispinterface IFooDisp
{
    ... properties & methods.
};
[ uuid(GUID_FOO_COCLASS),noncreatable ]
coclass FooDisp
{
    [default] dispinterface IFooDisp;
};
连接到以下接口

[ uuid(GUID_BAR) ]
interface IBar : IUnknown
{
    ... some methods
}

上述两种方法都是在注册的C++ OL/COM自动化DLL中实现的,并且使用类型库创建互操作DLL,并使用Rigase'D.P/> 因此,在C#中,我们可以成功地多次调用

myFoo as IBar

没有任何麻烦。直到

我们发现,如果我们打开一个网页,转到服务器上的URL,关闭浏览器并重复16次(Cassini或IIS),当创建第16个托管线程时,强制转换会突然失败,出现以下基本异常:

    Exception Thrown at 0x75151812 (KernelBase.dll) in My.exe: 
WinRT originate error - 0x80040155 : 'Failed to find proxy registration for IID: {GUID_BAR}.' 
测试时

(myFoo as IBar)!=null
演员阵容突然返回null。但是对象本身仍然有效,可以被询问,只是不再铸造


为什么它在第16个线程上失败,并且在之前工作良好?注意,一切都设置为STA。如何修复此问题?

我可以告诉您如何修复它,将
oleautomation
添加到IBar属性中。但我不知道为什么有必要

我是如何到达那里的?

给出了错误代码,我检查了注册表,从痛苦的经历中我知道,C#或OLE喜欢在注册表中定义接口,这样它就知道该做什么,而不是使用Interops/TLB的细节

在搜索时,我发现注册表没有包含GUID\u BAR作为键,因此没有代理/存根详细信息,就像所有其他接口一样

我想,如果它只需要注册表项就可以存在,那该怎么办呢? 因此,我一个接一个地添加属性,直到右边的一个将注册表设置推入,将
oleautomation
添加到IBar接口属性就成功了。它突然把它修好了,再也没有失败了

但我不知道为什么C#在第16个托管线程之前运行良好。每个线程都有自己的对象集(没有跨线程调用,并且托管线程与COM线程的映射为1:1)。在试图通过自动化测试重现这一点时,仅仅创建数百个线程并执行类似的工作不会导致相同的失败。这一定是IIS的特别之处


也许元数据被清除并重新收集?有人能再解释一下吗?

嗯,这不太明显。该属性只能由midl.exe用于为不兼容自动化的接口生成错误。我会更加担心web服务器上的WinRT错误,这是非常不可靠的。我认为oleautomation修复此问题的原因是,在这种情况下,typelib将提供对整理IBar接口的支持。请参阅:->“使用MIDL生成类型库,系统使用该类型库在运行时提供封送处理支持。这是实现封送处理支持的最简单方法。您所要做的就是生成类型库并注册它。您的接口必须与自动化兼容(oleautomation或dual),[…]”@MarcinZawiejski我相信你是对的,但这如何解释调用在第16个线程之前工作正常?不幸的是,我不知道为什么会发生这种情况。我最近遇到了一个编组问题,从WPF到COM对象的第一次调用总是成功,没有编组,而其他调用都失败了,即使线程看起来是相同的。
(myFoo as IBar)!=null