【问题标题】:COM Interop hang freezes entire COM system. How to cancel COM callCOM 互操作挂起冻结整个 COM 系统。如何取消 COM 通话
【发布时间】:2012-05-06 11:34:38
【问题描述】:

我正在使用通过 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 组件都会冻结代码。有什么我没有想到的,或者有什么方法可以让我的主线程不死?

更新

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

更新 2

上面的代码确实有效,并将 UI 线程的挂起延迟到下一次 COM 调用。这种尝试解决方法的原因是var deviceInfo = _myCom.get_DeviceInfo(0); 已经锁定了 UI 线程。但是,此信息并不重要,仅用于日志记录,因此这种方法是允许“15 秒后放弃并继续前进”的场景

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

【问题讨论】:

    标签: c# .net com interop


    【解决方案1】:

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

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

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

    由于您在 .NET 中实现此功能,您甚至可以在主可执行文件中将“包装 EXE”作为“嵌入式资源”,甚至可以从 RAM 启动它,而无需将其写入文件系统...

    【讨论】:

    • 我已更新我的问题以提供更多详细信息。如果您还需要更多,请告诉我
    • @JustinPihony 我用一种有助于您的方案的方法更新了我的答案...
    • 嗯,听起来这是最好的方法……不漂亮,但应该可以。非常感谢您的帮助
    • 为什么是 .EXE 而不是 AppDomain?
    • @HenkHolterman 以我在相当恶劣的情况下的经验,操作系统(进程边界)提供的隔离优于 .NET 在使用 AppDomain 时提供的隔离(一个表现非常糟糕的 AppDomain 仍然可以降低整个过程也将包含“主 AppDomain”)...
    【解决方案2】:

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

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

    最好联系此第三方产品的开发人员/供应商,并询问他们您是否以某种方式滥用它。是否缺少一些先决条件。一些未执行的初始化。一些必要的配置等。

    【讨论】:

      猜你喜欢
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 2010-12-14
      • 1970-01-01
      • 2011-04-13
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多