C# 后台工作者 - 如何触发它执行重复任务

发布于 2024-12-19 06:05:15 字数 1702 浏览 5 评论 0原文

我正在从串行端口接收数据,将每一行放入队列中,然后将这些行出队,稍微格式化它们(删除一些前导字符,修剪等),然后在列表框中显示格式化的行。

我使用计时器每 200 毫秒触发一次出队方法。一切正常,但似乎有点迟缓/缓慢。

我正在考虑使用 BackgroundWorker 来处理出队和格式化,但我陷入困境。

我尝试在 FormLoad 中启动后台工作程序,但很快意识到它只会运行一次代码。我尝试使用标签并转到后台工作程序代码内部来创建循环(我知道,这不好),但这使我的 CPU 使用率很高,甚至不起作用。

我还尝试在我的串行接收事件中使用“backgroundWorker1.RunWorkerAsync();”在每次新数据进入时运行它,但这会引发“后台工作人员当前繁忙”异常

所以,我需要后台工作人员不断处理队列(代码

:这是我的数据接收事件,下面是我的出队代码,非常感谢

//  Serial Data Received
private void serialPort1_DataReceived(
    object sender, 
    System.IO.Ports.SerialDataReceivedEventArgs e)
{
    RxString = serialPort1.ReadTo("\u0003");
    q.Enqueue(RxString);
}

下一个代码是出队代码:

//  Dequeue items, format, then display in listbox
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    if (q.Count == 0)
    {
        // do nothing if q is empty
    }
    else
        do
        {
            output = (q.Dequeue().ToString());
            output = output.TrimStart(new char[] { (char)02 }); 
            output = output.TrimEnd(new char[] { (char)03 });

            if (output.StartsWith("C"))
            {
                ClearAll();
            }
            else if (output.StartsWith("W98"))
            {
                txtTax.Text = (output.Remove(0, 5));
            }
            else if (output.StartsWith("W99"))
            {
                txtTotal.Text = (output.Remove(0, 24));
            }
            else
            {  
                listOrderItems.Items.Add(output.Remove(0, 5));
                listOrderItems.SelectedIndex = listOrderItems.Items.Count - 1;
            }
        } while (q.Count > 0);
}

I am receiving data from a serial port, placing each line into a queue and then de-queuing the lines, formatting them slightly (removing some leading characters, trimming etc), and then displaying the formatted lines in a listbox.

I am using a Timer to fire the Dequeuing method every 200ms. Everything is working but it seems to be a bit sluggish/slow.

I am considering using a BackgroundWorker to handle the de-queuing and formatting but im getting stuck.

I tried to start the backgroundworker in FormLoad, but quickly realized it would run through the code only once. I tried a label and goto inside the backgroundworker code to create a loop (i know, not good) but that got me high CPU usage and didnt even work.

I also tried using " backgroundWorker1.RunWorkerAsync(); " in my serial received event to run it every time new data comes in but that throws the 'Background worker currently busy" exception

So, I need the background worker to continuously process the queue (dequeue).

Code: heres my data received event, and below that my dequeuing code thats sitting in the backgroundworker. Any help much appreciated.

//  Serial Data Received
private void serialPort1_DataReceived(
    object sender, 
    System.IO.Ports.SerialDataReceivedEventArgs e)
{
    RxString = serialPort1.ReadTo("\u0003");
    q.Enqueue(RxString);
}

Next Code is the dequeue code:

//  Dequeue items, format, then display in listbox
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    if (q.Count == 0)
    {
        // do nothing if q is empty
    }
    else
        do
        {
            output = (q.Dequeue().ToString());
            output = output.TrimStart(new char[] { (char)02 }); 
            output = output.TrimEnd(new char[] { (char)03 });

            if (output.StartsWith("C"))
            {
                ClearAll();
            }
            else if (output.StartsWith("W98"))
            {
                txtTax.Text = (output.Remove(0, 5));
            }
            else if (output.StartsWith("W99"))
            {
                txtTotal.Text = (output.Remove(0, 24));
            }
            else
            {  
                listOrderItems.Items.Add(output.Remove(0, 5));
                listOrderItems.SelectedIndex = listOrderItems.Items.Count - 1;
            }
        } while (q.Count > 0);
}

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

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

发布评论

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

评论(1

橘虞初梦 2024-12-26 06:05:15

我没有看到在不同线程中解析字符串的意义。它不是一个长时间运行的过程,并且由于您在后台线程中运行,因此您似乎忘记Invoke到Windows线程。这是我的解决方案,

using System.IO.Ports;    


static void ParseData(ref string data)
{
    data = data.TrimStart(new char[] { (char)02 }); 
    data = data.TrimEnd(new char[] { (char)03 });  
}    

private void UpdateControlsWithData(string data)
{
    Action action;
    if(data.StartsWith("C")
    {
        action = () => ClearAll();
    }
    else if(data.StartsWith("W98"))
    {
        action = () => { txtTax.Text = data.Remove(0, 5); };
    }
    else if(data.StartsWith("W99"))
    {
        action = () => { txtTotal.Text = data.Remove(0, 24); };
    }
    else
    {
        action = () => { 
            listOrderItems.Items.Add(data.Remove(0, 5));
            listOrderItems.SelectedIndex = listOrderItems.Items.Count - 1;
        };
    }
    if(this.InvokeRequired()) this.Invoke(action);
    else action();
}

private void HandleDataReceived()
{
    string data = serialPort1.ReadTo("\u0003");
    ParseData(ref data);
    UpdateControlsWithData(data);
}

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    this.HandleDataReceived();
}

i do not see the point parsing your string in a different thread. it is not a long running procedure, and since your running in the background thread, it seems that you forgot to Invoke to the windows thread. here is my solution,

using System.IO.Ports;    


static void ParseData(ref string data)
{
    data = data.TrimStart(new char[] { (char)02 }); 
    data = data.TrimEnd(new char[] { (char)03 });  
}    

private void UpdateControlsWithData(string data)
{
    Action action;
    if(data.StartsWith("C")
    {
        action = () => ClearAll();
    }
    else if(data.StartsWith("W98"))
    {
        action = () => { txtTax.Text = data.Remove(0, 5); };
    }
    else if(data.StartsWith("W99"))
    {
        action = () => { txtTotal.Text = data.Remove(0, 24); };
    }
    else
    {
        action = () => { 
            listOrderItems.Items.Add(data.Remove(0, 5));
            listOrderItems.SelectedIndex = listOrderItems.Items.Count - 1;
        };
    }
    if(this.InvokeRequired()) this.Invoke(action);
    else action();
}

private void HandleDataReceived()
{
    string data = serialPort1.ReadTo("\u0003");
    ParseData(ref data);
    UpdateControlsWithData(data);
}

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