我正在使用后台线程通过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.
}
}
}
}
编辑:也许不清楚我的意思。通过'挂'我应该说'暂时冻结'。
答案 0 :(得分:3)
仪表是否需要在STA中运行?由于这个原因,对Open()的调用是否实际被编组回UI线程?
您可以通过查看调试器中挂起的UI线程的callstack来验证这是真的。
答案 1 :(得分:2)
FancyVoltmeter的实例化需要多长时间?难道不是Open方法导致UI冻结,而是创建COM对象(在UI线程上完成)?
如果情况确实如此,那么在新的,单独的工作线程上移动创建此对象应该可以解决问题。
编辑:我现在看到你在迈克尔的评论中已经发现了这一点......
答案 2 :(得分:0)
我建议你在一个单独的方法中包含对meter.open()的调用,并使用表单或父控件上的Invoke()或BeginInvoke()构造从updateMeter()方法中调用该方法。这样做会将操作封送回UI线程,并且应该正常执行。我希望这会有所帮助。
答案 3 :(得分:0)
考虑使用BackgroundWorker完成此任务。