2012-04-25 59 views
1

我正在使用通過COM Interop包裝器公開的第三方dll。但是,其中一個COM調用通常會凍結(永遠不會返回)。爲了儘量至少使我的代碼更健壯,我包的異步調用(_getDeviceInfoWaiterManualResetEventCOM Interop hang凍結整個COM系統。如何取消COM調用

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秒後繼續」場景

這裏的另一個解決方法是找到一種方法來取消COM x秒後通話?

回答

3

更新 - 從OP第二更新後

如果你有一些問題的組件,你可以隨時讓你對它的使用更強大的使用以下方法:

創建過程( EXE),它包裝了該組件的使用並公開了一個API(例如通過任何IPC機制)。然後,您可以將該EXE作爲一個獨立的進程(從主EXE)啓動並使用它...如果您需要在特定時間後和/或遇到某種情況時殺死該組件,則始終可以殺死該「包裝EXE」從你的主EXE ...根據具體的組件,它可能甚至是有用的執行一些特殊的「清理代碼」(可能在一個單獨的線程)在「包裝EXE」,當你需要殺死「包裝EXE」 」。

既然你是在.NET實現這一點,你甚至可以有「包裝EXE」在你的主執行「嵌入的資源」,並從RAM甚至啓動它,而不將其寫入到文件系統...

+0

我已更新我的問題以提供更多詳細信息。讓我知道,如果你仍然需要更多 – 2012-04-25 19:37:37

+0

@JustinPihony我用一種方法更新了我的答案,這將有助於您的方案... – Yahia 2012-04-25 21:09:04

+0

嗯,這聽起來像這是最好的方式...不漂亮,但它應該工作。我非常感謝幫助 – 2012-04-25 21:20:13

1

的第三方DLL有一些不確定的等待,循環或死鎖。嘗試像這樣解決它是行不通的。你可能已經對工作者線程進行了懸掛調用,但該線程不會消失;它一直掛在那個電話裏。

對COM組件的下一次調用很可能因爲前一個凍結而凍結。也許它試圖獲得前一個掛起之前獲得的鎖。或者可能是因爲完全相同的原因而懸掛,而不是依賴的原因。

更好地聯繫第三方的開發者/供應商,並問他們是否以某種方式濫用它。有一些缺失的先決條件嗎?一些未執行的初始化。一些必要的配置等