COM互挂冻结整个COM系统。 如何取消COM调用(COM Interop hang freez

2019-09-16 18:31发布

我使用的是通过COM互操作包装暴露第三方DLL。 然而,COM调用一个经常死机(不返回至少)。 为了尽量至少使我的代码更健壮,我异步的调用包装( _getDeviceInfoWaiterManualResetEvent

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

基本上,这是每当一个新的设备插入到PC,使我们可以适当地将这些信息记录被称为COM调用。 然而,正如我所说, 任何 COM组件将如果一个正在等待(我们自己锁自定义COM如果第三方锁定)冻结

更新2

上面的代码不工作,并延迟UI线程的悬挂,直到下一个COM调用。 这样做的原因试图解决方法是因为var deviceInfo = _myCom.get_DeviceInfo(0); 已经锁定在UI线程。 然而,这个信息并不重要,只用于记录,所以这种方法是允许“放弃了15秒后继续前进”的情景

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

Answer 1:

更新-从OP第二更新后

如果你有一些问题的组件可以随时让你对它的使用更强大的使用以下方法:

创建一个进程(EXE),其(通过任何IPC机制例如)包装了元件的使用和暴露的API。 然后,您可以启动EXE作为单独的进程(从主EXE),并用它...如果你需要一定的时间后杀死部件和/或当某些条件得到满足,你可以随时杀死“包装EXE”从您的主EXE ...这取决于特定的组件上,当你需要杀死“包装EXE它甚至可能是其被执行的“包装EXE”中实现一些特殊的“清理代码”(可能在一个单独的线程)有用”。

既然你是在.NET实现这一点,你甚至可以有“包装EXE”在你的主执行“嵌入的资源”,并从RAM甚至启动它,而不将其写入到文件系统...



Answer 2:

第三方DLL具有某种不确定的等待,循环或死锁里面的。 试图解决它像这样将无法正常工作。 你可能已经租出去了挂电话的工作线程,但该线程不会消失; 它一直挂在这一呼吁。

在COM组件的下一个呼叫冻结很可能是因为前一个僵住了。 也许它试图获取了前一个挂之前获取的锁。 或者,也许它的悬挂完全相同的原因,而不是依赖的原因。

更好地接触这个第三方的事情开发商/供应商,并要求他们,如果你以某种方式滥用它。 有一些缺失的前提条件。 未进行一些初始化。 一些必要的配置,等等。



文章来源: COM Interop hang freezes entire COM system. How to cancel COM call