如何结束内部有Dispatcher调用的子线程



我正在构建一个应用程序,它不断地从设备中提取数据并更新到UI。

一旦我点击一个开始按钮,一个子线程被创建,里面有一个while循环,每200ms从设备读取数据,然后我调用调度程序。

将此值更新到GUI。
while(true)
{
if (!IsPowerOn)
{
Console.WriteLine("background thread else exit"); 
break;
}
else
{
try
{
if (session.IsDisposed || session == null) break;
session.RawIO.Write("MEAS:VOLT?r");
var volt = session.RawIO.ReadString();                    
Dispatcher.Invoke(() => VoltOutput = float.Parse(volt));
Console.WriteLine(volt);

if (session.IsDisposed || session == null) break;
session.RawIO.Write("MEAS:CURR?r");
var curr = session.RawIO.ReadString();
Console.WriteLine(curr);
Action<string> action1 = delegate (string s) { CurrOutput = float.Parse(s); };
Dispatcher.Invoke(action1, curr);

Thread.Sleep(200);
Console.WriteLine("sleep");
}
catch (Exception)
{
session.Clear();
Console.WriteLine("background thread except exit");
break;
}
}
}

在主线程中,如果我点击Stop按钮,IsPower = false;thread.join ();被称为。但这将导致程序卡住。似乎调度员被困在这里了。不知道调度程序是被非正常终止还是仍在工作。无论哪种方式,主线程都没有响应thread.join.

希望有人能给我一些提示,或者像这样的应用程序的常见做法

感谢

看起来像是死锁。在bg线程中,您期望GUI线程处理Dispatcher.Invoke,但GUI线程在Button.Click通过thread.join()的事件处理程序中被阻塞。

避免

  • fire&forgetDispatcher.InvokeAsync
  • 或使事件处理程序Button.Clickasync并调用await Task.Run(()=>{thread.join();});
  • 或者不调用thread.join()/不等待线程完成。你可以在程序逻辑的其他部分检查线程状态,以确保线程已经完成。

我不知道数据抓取有多快,但为了使停止更灵敏,你可以尝试在(session.IsDisposed || session == null)Thread.Sleep之前添加IsPowerOn的检查。

最新更新