You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何同步BackgroundWorker与串口操作以避免竞争条件?

串口访问线程同步解决方案咨询

我通过BackgroundWorker实现每30秒更新Form控件:后台线程打开COM端口读取仪器数据,再通过ReportProgress()更新UI。同时Form上的ToggleSwitch也需要打开同一个COM端口修改仪器状态,为避免串口访问的竞争条件,必须在ToggleSwitch.StateChanged触发时暂停BackgroundWorker,保证同一时间只有一个线程访问串口。

以下是我的代码片段:

private void BackgroundWorkerStatus_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        while (!BackgroundWorkerStatus.CancellationPending)
        {
            // 获取新值(打开COM端口,读取状态)
            ReadState();

            // 更新用户界面
            BackgroundWorkerStatus.ReportProgress(0);

            // 等待下次更新
            Thread.Sleep(UpdateInterval);
        }
    }
    catch
    {
        MessageBox.Show(….)
    }
}

private void BackgroundWorkerStatus_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    try
    {
         // 更新Form上的控件
    }
    catch
    {
        MessageBox.Show(….);
    }
}

private void ToggleSwitch_StateChanged(object sender, NationalInstruments.UI.ActionEventArgs e)
{
        // 打开COM端口,设置状态,更新Form
}

我已经尝试过两种方法但都无效:

  • 在StateChanged事件开头调用CancelAsync(),操作完成后调用RunWorkerAsync()重启后台线程,但因为后台线程运行到中途时才检测CancellationPending,无法及时终止当前的串口访问操作。
  • 用全局布尔变量标记是否需要暂停,在DoWork循环中判断,但同样存在检测不及时的问题。

我还试过用Semaphore做同步,但导致后台线程更新UI时出现跨线程异常,虽然知道原因但不知道怎么解决。

本质上我需要结合Semaphore和BackgroundWorker来同步这个可更新UI的后台任务,请问合适的实现方式是什么?

内容的提问来源于stack exchange,提问作者Dan Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:29:56