COM Interop挂起冻结整个COM系统。 如何取消COM通话

我正在使用通过COM Interop包装器公开的第三方dll。 但是,其中一个COM调用经常冻结(至少不会返回)。 为了尝试至少使我的代码更健壮,我异步地包装了调用( _getDeviceInfoWaiter是一个ManualResetEvent

 var backgroundWorker = new BackgroundWorker(); backgroundWorker.DoWork += (sender, eventArgs) => { var deviceInfo = _myCom.get_DeviceInfo(0); _serialNumber = deviceInfo.SerialNumber; _getDeviceInfoWaiter.Set(); }; backgroundWorker.RunWorkerAsync(); var waitFifteenSecondsForGetInfo = new TimeSpan(0, 0, 0, 15); _getDeviceInfoWaiter.WaitOne(waitFifteenSecondsForGetInfo, true); if(String.IsNullOrEmpty(_serialNumber)) throw new ArgumentNullException("Null or empty serial number. " + "This is most likely due to the get_DeviceInfo(0) COM call freezing."); 

但是,对下一个COM组件的调用将冻结代码。 有什么我没有想到的,或者是否有某种方法可以防止我的主线死亡?

UPDATE

基本上,这是一个COM调用,只要将新设备插入PC就会调用它,以便我们可以适当地记录信息。 但是,正如我所说,如果这个组件正在等待, 任何 COM组件都会冻结(如果第三方锁定,我们自己锁定的自定义COM)

更新2

上面的代码可以工作,并延迟UI线程的挂起,直到下一个COM调用。 尝试解决此问题的原因是因为var deviceInfo = _myCom.get_DeviceInfo(0); 已经锁定了UI线程。 但是,此信息并不重要,仅用于记录,因此这种方法允许“在15秒后放弃并继续”方案

这里的另一个解决方法是找到一种在x秒后取消COM调用的方法吗?

更新 – 在OP的第二次更新之后

如果您有一些有问题的组件,您可以使用以下方法始终使用它更加健壮:

创建一个进程(EXE),它包装该组件的使用并公开API(例如通过任何IPC机制)。 然后,您可以将EXE作为一个单独的进程(来自您的主EXE)启动并使用它…如果您需要在一定时间后杀死该组件和/或满足某些条件,您可以随时杀死“包装器EXE”从您的主要EXE …取决于具体组件,甚至可能有用的是在“包装器EXE”中实现一些特殊的“清理代码”(可能在一个单独的线程中),当您需要杀死“包装器EXE”时执行它”。

由于您在.NET中实现了这一点,您甚至可以将“wrapper EXE”作为“嵌入式资源”放在主可执行文件中,甚至可以从RAM启动它而无需将其写入文件系统…

第三方DLL内部有某种无限期的等待,循环或死锁。 试图像这样解决它是行不通的。 你可能已经对工作线程进行了挂起调用,但该线程并没有消失; 它一直挂在那个电话里。

对COM组件的下一次调用最有可能冻结,因为前一个组件冻结了。 也许它正在尝试获得前一个在挂起之前获得的锁。 或者它可能因为完全相同的原因而悬挂,而不是依赖的原因。

更好地联系这个第三方的开发商/供应商,并询问他们是否以某种方式滥用它。 是否有一些缺失的前提条件。 一些未执行的初始化。 一些必要的配置等