C# 无法强制转换类型为exception的COM对象
我有以下代码:C# 无法强制转换类型为exception的COM对象,c#,com,interface,C#,Com,Interface,我有以下代码: public void Test(IMyInterface iInterface) { iInterface.CallMethod ( ); } 这很好用。但是,如果我将代码更改为线程化: private IMyInterface myInterface; public void Test(IMyInterface iInterface) { myInterface = iInterface; new Thread ( new ThreadStart ( CallI
public void Test(IMyInterface iInterface)
{
iInterface.CallMethod ( );
}
这很好用。但是,如果我将代码更改为线程化:
private IMyInterface myInterface;
public void Test(IMyInterface iInterface)
{
myInterface = iInterface;
new Thread ( new ThreadStart ( CallInterfaceMethod) ).Start ( );
}
public void CallInterfaceMethod ( )
{
myInterface.CallMethod ( )
}
当我使用线程时,我收到异常:
无法将“System.\u ComObject”类型的COM对象强制转换为接口类型“IMyInterface”。
此操作失败,因为对IID为“{GUID}”的接口的COM组件的QueryInterface调用失败,原因是出现以下错误:不支持此类接口
但是界面应该得到很好的支持?有人对这里发生的事情有什么想法吗?首先,您正在对一个对象进行跨线程调用,但没有锁定它,这会自动导致一些问题。您的代码应该更像:
private IMyInterface myInterface;
private static readonly object _myObjectLock = new object();
public void Test(IMyInterface iInterface)
{
myInterface = iInterface;
new Thread ( new ThreadStart ( CallInterfaceMethod) ).Start ( );
}
public void CallInterfaceMethod ( )
{
lock(_myObjectLock)
{
myInterface.CallMethod ( );
}
}
据我所知,您列出的错误有时会在无法访问资源时发生,而在这样的跨线程操作中,这种情况最有可能发生。不过,不要引用我的话,我不是COM专家
老实说,我不认为我会用这种方式来称呼这个方法,因为这样做有太多的风险。你有没有考虑过使用一种方法,并通过这种方式传递对象?您仍然需要为跨线程操作安全地锁定对象,但这样会更安全
此外,请检查以确保“myInterface”类仍然可以调用“CallMethod()”方法。接口没有实现,当您设置“myInterface=iInterface”时,可能会遇到问题。这种令人讨厌的异常是由于一种称为COM编组的概念而产生的。问题的本质在于,为了从任何线程使用COM对象,线程必须能够访问描述COM对象的类型信息 在您描述的场景中,它在第二个线程上失败的原因是第二个线程没有接口的类型信息 您可以尝试将以下内容添加到代码中:
[ComImport]
[Guid("23EB4AF8-BE9C-4b49-B3A4-24F4FF657B27")]
public interface IMyInterface
{
void CallMethod();
}
基本上,上面的声明指示.NET framework COM加载器使用传统技术从注册表加载类型信息,并找到关联的类型库,然后从那里开始
还应将COM对象的创建限制为单个线程(以防止线程编组),以帮助解决此问题
总之,此错误与类型信息和线程编组有关。确保要访问COM对象的每个线程都具有相关信息,以便从源线程解组该对象
PS:这个问题在.NET4.0中使用了一种称为“类型等价”的技术解决了。我得到了一个建议,它帮助了我 在主线程(Program.cs)中找到[STAThread]行并将其更改为[MTAThread]。我一直在开发一个通过COM接口使用7-zip的C#应用程序。我遇到了一件有趣的事情,在一个实例中,我能够从一个工作线程中提取归档,但在另一个实例中,我却没有,得到了同样的异常
我发现,只要在使用它的线程中初始化有问题的COM对象,就不会引发异常。我的解决方案是处置使用COM接口的对象,并在线程之间传递它们时重新初始化它们。答案比您更清楚,但使用ParameterizedThreadStart也不起作用(带锁或不带锁)。我还检查过,一旦设置了myInterface(myInterface=iInterface),myInterface仍然可以“CallMethod”。跨线程对象访问并不总是自动导致问题。例如,对于只读访问,不需要锁定。2.关于最后一段,您不能将接口作为对象传递,因此即使将非null对象分配给具有接口(静态)类型的变量,并且代码已编译,也可以调用所有这些方法。将静态类型(接口)看作是另一种实现类型的某种外观。感谢您的回复。你的解释是有道理的,在MSDN上查找ComImport的免责条款似乎也是有道理的。干杯。这是我的荣幸:)我以前遇到过这个问题,这是一个需要尝试解决的噩梦,直到灯泡熄灭,我最终消耗了创建COM对象的线程中的COM对象。[+1]谢谢大家!对我来说,错误是[StatThread]丢失了。这个问题和答案让我在阅读线程问题后找到了它。ComImport和Guid就是它!为了使我的包装器单元可测试并隔离COM组件,我正在努力处理相同的强制转换异常(与线程无关)。谢谢你能解释一下变化吗?