C#库的背景工作者

发布于 2025-01-31 03:17:35 字数 910 浏览 3 评论 0 原文

我已经集成了easymodbus库,现在想使用后台工作者每250ms通过modbus查询值。消息modbusclient为null出现在后台工作者中。如何在后台工作者中获得modbusclient函数?有什么方法可以添加功能吗?

private void backgroundworker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        label10.Text = modbusclient.ReadInputRegisters(4, 1)[0].ToString() + " kHz"; //read register 300005 for frequency
        label11.Text = modbusclient.ReadInputRegisters(5, 1)[0].ToString() + " W"; //read register 300006 for power
        label12.Text = modbusclient.ReadInputRegisters(6, 1)[0].ToString() + " %"; //read register 300007 for amplitude in %
        TimeSpan t = TimeSpan.FromMilliseconds(Convert.ToDouble(modbusclient.ReadInputRegisters(8, 1)[0].ToString()));
        string runningtime = string.Format("{0:D2}m:{1:D2}s",
                            t.Minutes,
                            t.Seconds);
        label14.Text = runningtime;
    }

I have integrated the EasyModBus Library and would now like to use the background worker to query values every 250ms via the ModBus. The message modbusclient is null appears in the background worker. How can I get the modbusclient function in the background worker? Is there any way to add a function?

private void backgroundworker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        label10.Text = modbusclient.ReadInputRegisters(4, 1)[0].ToString() + " kHz"; //read register 300005 for frequency
        label11.Text = modbusclient.ReadInputRegisters(5, 1)[0].ToString() + " W"; //read register 300006 for power
        label12.Text = modbusclient.ReadInputRegisters(6, 1)[0].ToString() + " %"; //read register 300007 for amplitude in %
        TimeSpan t = TimeSpan.FromMilliseconds(Convert.ToDouble(modbusclient.ReadInputRegisters(8, 1)[0].ToString()));
        string runningtime = string.Format("{0:D2}m:{1:D2}s",
                            t.Minutes,
                            t.Seconds);
        label14.Text = runningtime;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紫轩蝶泪 2025-02-07 03:17:35

我的建议是抛弃 anchronistic code> coded> copderctworker coce> Codeckers Codefworker ,并使用 task /code> 。首先创建一个异步方法,该方法将连续每250毫秒连续循环并更新标签:

private async Task InfiniteLoopAsync(CancellationToken cancellationToken = default)
{
    while (true)
    {
        var delayTask = Task.Delay(250, cancellationToken);
        var value10 = await Task.Run(() => modbusclient.ReadInputRegisters(4, 1)[0]);
        var value11 = await Task.Run(() => modbusclient.ReadInputRegisters(5, 1)[0]);
        var value12 = await Task.Run(() => modbusclient.ReadInputRegisters(6, 1)[0]);
        var value14 = await Task.Run(() => modbusclient.ReadInputRegisters(8, 1)[0]);
        label10.Text = value10.ToString() + " kHz";
        label11.Text = value11.ToString() + " W";
        label12.Text = value12.ToString() + " %";
        TimeSpan t = TimeSpan.FromMilliseconds(Convert.ToDouble(value14));
        label14.Text = $"{t.Minutes:D2}m:{t.Seconds:D2}s";
        await delayTask;
    }
}

然后在首次显示表单时启动异步循环,并在表单即将关闭时最终停止循环:

private CancellationTokenSource _cts = new();
private Task _infiniteLoop = Task.CompletedTask;

private void Form_Shown(object sender, EventArgs e)
{
    _infiniteLoopTask = InfiniteLoopAsync(_cts.Token);
}

private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
    _cts.Cancel();
    // Wait the completion of the loop before closing the form
    try { _infiniteLoopTask.GetAwaiter().GetResult(); }
    catch (OperationCanceledException) { } // Ignore this error
}

重要的是,与任何互动都必须与任何交互UI控件仅在UI线程上发生。您只能将代码卸载到 > 仅当此代码既没有读取或更新UI组件时。使用等待任务。lun您将递给卸载操作的结果,然后您回到UI线程中,更新标签是合法的。

My suggestion is to ditch the anachronistic BackgroundWorker class, and use Task.Run and async/await instead. First create an asynchronous method that will loop continuously every 250 msec and will update the labels:

private async Task InfiniteLoopAsync(CancellationToken cancellationToken = default)
{
    while (true)
    {
        var delayTask = Task.Delay(250, cancellationToken);
        var value10 = await Task.Run(() => modbusclient.ReadInputRegisters(4, 1)[0]);
        var value11 = await Task.Run(() => modbusclient.ReadInputRegisters(5, 1)[0]);
        var value12 = await Task.Run(() => modbusclient.ReadInputRegisters(6, 1)[0]);
        var value14 = await Task.Run(() => modbusclient.ReadInputRegisters(8, 1)[0]);
        label10.Text = value10.ToString() + " kHz";
        label11.Text = value11.ToString() + " W";
        label12.Text = value12.ToString() + " %";
        TimeSpan t = TimeSpan.FromMilliseconds(Convert.ToDouble(value14));
        label14.Text = 
quot;{t.Minutes:D2}m:{t.Seconds:D2}s";
        await delayTask;
    }
}

Then start the asynchronous loop when the form is first shown, and eventually stop the loop when the form is about to close:

private CancellationTokenSource _cts = new();
private Task _infiniteLoop = Task.CompletedTask;

private void Form_Shown(object sender, EventArgs e)
{
    _infiniteLoopTask = InfiniteLoopAsync(_cts.Token);
}

private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
    _cts.Cancel();
    // Wait the completion of the loop before closing the form
    try { _infiniteLoopTask.GetAwaiter().GetResult(); }
    catch (OperationCanceledException) { } // Ignore this error
}

It's important that any interaction with the UI controls happens exclusively on the UI thread. You can only offload code to the ThreadPool only if this code neither reads or updates UI components. With the await Task.Run you are handed the result of the offloaded operation, and you are back on the UI thread where it's legal to update the labels.

说谎友 2025-02-07 03:17:35

通过您的问题,我注意到Winform平台的存在。

我的建议是您使用计时器实现。

它与您要在上面尝试实现的背景工作者有些相似。不同之处在于,您将将 Interval 属性的值设置为 250 ,以便在250ms之后事件tick中的代码将触发以运行。

此外,您还需要添加条件如果(modBusClient == null)返回; line在每个事件执行之前,这可以帮助您避免异常。

而且,不要忘记检查 modBusClient 在开始启动 timer.start()之前初始化了!

参考:

Through your problem, I noticed the presence of winform platform.

My suggestion is that you implement using Timer.

It is somewhat similar to the BackgroundWorker you are trying to implement above. The difference is that you will set the value for the Interval property to 250 so that after 250ms the code in event Tick will be triggered to run.

In addition, you also need to add the conditional if (modbusclient == null) return; line before every event's execution, this helps you avoid exceptions.

And don't forget to check that modbusclient is initialized before starting to Timer.start()!!

Reference: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.timer?view=netframework-4.7.2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文