2010-04-26 165 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线程中。如果这是你的情况,我相信你唯一的选择是诉诸工作者进程而不是工作者线程。