2010-04-26 130 views
4

我正在研究通過第三方COM庫與外部設備通信的應用程序。我試圖讓設備的所有通信都通過後臺線程來防止通信中出現的問題,從而破壞我的應用程序,並擺脫通過在UI線程中進行通信而引入的其他一些複雜性。UI線程阻塞調用COM對象的後臺線程

問題是,無論何時發生導致主UI線程阻塞的事件(即MessageBox.Show被調用,甚至只是在窗口周圍移動窗口),後臺線程上的設備通信也會停止。

有沒有什麼辦法(短缺完全獨立的進程)將兩條線程分開得足夠遠以至於它們不會互相干擾? (請注意,與一些數學計算完全相同的代碼,可以稍微減慢一些效果,這只是在我使用COM庫時纔有問題)

+3

這似乎很奇怪。沒有看到你的代碼,很難確切地知道爲什麼使UI線程忙碌減慢你的其他線程。工作線程上是否有可能正在等待UI線程執行某些操作的任何東西? – 2010-04-26 20:05:15

+1

你的後臺線程是否告訴UI使用'Invoke'彈出一個消息框? – Paolo 2010-04-26 20:08:52

+0

@Paolo,聽起來這比彈出一個消息框或類似的東西要頻繁得多。據推測,他並沒有彈出如此多的消息框來抓住窗口,並且移動它導致放緩。 :) – 2010-04-26 20:12:51

回答

11

您觀察到的行爲可以解釋如果以下兩個條件是正確的。

  • 第三方COM庫的設計,在單線程公寓
  • 您從庫UI線程

上創建一個類的實例,因爲UI線程運行時運行在STA(單線程單元)中,並且在該線程上創建了COM類,則所有對源於非UI線程的線程的類的調用將被整理到UI線程本身。如果UI線程被阻塞,那麼對COM類的所有調用也會被阻塞。

+1

這個伎倆。 COM對象在被切換到工作線程之前正在UI線程中創建。當我將其移入工作線程本身時,問題就消失了。 – AlphaKilo 2010-05-24 14:15:00

2

我想填寫Brian的答案。

難道是你忘記給你的工作線程調用TrySetApartmentState(ApartmentState.STA)?如果是這樣,我相信你的工作線程默認運行在MTA中,並且所有的STA對象都是在單獨的STA線程(甚至可能是主UI線程)上創建的。你應該確保你的工作線程加入一個STA,看看是否有幫助。

除此之外,COM對象可以註冊爲主STA。 IIRC,這是不常見的。主STA對象MUST居住在主UI線程中。如果這是你的情況,我相信你唯一的選擇是訴諸工作者進程而不是工作者線程。