后台线程如何挂起UI线程?

我正在使用后台线程通过USB初始化仪器。 当我尝试打开设备时,UI挂起。 我希望后台线程在设备上调用Open时暂停,但不是UI线程。 我正在测试这个没有来自后台线程的UI交互。 我不知道如何调试这个问题,这个问题太广泛了,但也许有人之前已经看过这样的事情了。 据我所知,ActiveX互操作没有任何问题,设备正常工作。 这是一般方法:

using System; using FancyVoltmeterLibrary; namespace SOQuestion { public class MeterClass { private FancyVoltmeter meter; private Thread meterThread; public MeterClass() { // Create instance of ActiveX/COM object. meter = new FancyVoltmeter(); meterThread = new Thread(UpdateMeter); meterThread.Name = "Meter Thread"; meterThread.Priority = ThreadPriority.Normal; meterThread.IsBackground = true; meterThread.Start(); } private void UpdateMeter() { while(true) { Thread.Sleep(1000); if(!meter.IsOpen()) { // Meter may be powered off here. // The call to Open takes about 1 second. // UI hangs during the call??? meter.Open(); } // code to read meter goes here. } } } } 

编辑:也许不清楚我的意思。 通过’挂’我应该说’暂时冻结’。

仪表是否需要在STA中运行? 由于这个原因,对Open()的调用是否实际上被编组回UI线程?

您可以通过查看调试器中挂起的UI线程的callstack来validation这是真的。

FancyVoltmeter的实例化需要多长时间? 难道不是Open方法导致UI冻结,而是创建COM对象(在UI线程上完成)?

如果事实certificate是这种情况,那么在新的,单独的工作线程上移动此对象的创建应该解决问题。

编辑:我现在看到你已经在迈克尔的评论中发现了这一点……

我建议你在一个单独的方法中包含对meter.open()的调用,并使用表单或父控件上的Invoke()或BeginInvoke()构造从updateMeter()方法中调用该方法。 这样做会将操作封送回UI线程,并且应该正常执行。 我希望这有帮助。

考虑使用BackgroundWorker执行此任务。