C#背景工作者-如何为重复性任务触发它

C#背景工作者-如何为重复性任务触发它,c#,backgroundworker,deque,C#,Backgroundworker,Deque,我从一个串行端口接收数据,将每一行放入一个队列,然后对这些行进行解队列,稍微格式化(删除一些前导字符、修剪等),然后在列表框中显示格式化的行 我使用定时器每200毫秒触发一次排队方法。一切正常,但似乎有点慢 我正在考虑使用BackgroundWorker来处理去排队和格式化,但是我被卡住了 我试图在FormLoad中启动backgroundworker,但很快意识到它只能在代码中运行一次。我尝试在backgroundworker代码中添加一个标签并创建一个循环(我知道,不太好),但这让我的CPU

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

我使用定时器每200毫秒触发一次排队方法。一切正常,但似乎有点慢

我正在考虑使用BackgroundWorker来处理去排队和格式化,但是我被卡住了

我试图在FormLoad中启动backgroundworker,但很快意识到它只能在代码中运行一次。我尝试在backgroundworker代码中添加一个标签并创建一个循环(我知道,不太好),但这让我的CPU使用率很高,甚至无法工作

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

因此,我需要后台工作人员连续处理队列(出列)

代码:这是我的data received事件,下面是我在backgroundworker中的出列代码。非常感谢您的帮助

//  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);
}

我看不出在其他线程中解析字符串有什么意义。这不是一个很长的运行过程,而且由于您在后台线程中运行,您似乎忘记了调用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();
}

线程太多。你已经有一只手放在银盘上了:DataReceived事件在线程池线程上运行。在那里执行消息处理。然后使用Control.BeginInvoke更新任何UI。@Hans:答案在下面(即使是简短的答案)它并没有回答这个问题,用户对此会感到不安。Hans,你的评论是否意味着DataReceived事件已经在类似BackgroundWorker的程序中运行?如果是,你的“太多线程”评论是否意味着创建额外线程不好?如何确定有多少线程太多?当你说。“在那里处理消息吗“您的意思是将所有格式代码移到DR事件中吗??如果是这样,这就引出了另一个问题:我甚至需要BgW吗?我需要这是回应。这个程序不会做任何太复杂的事情,但我需要它快速稳定。我把我的格式化代码放入DataRec。事件处理程序。它一点也不好用。作为礼貌性的跟进,我确实不需要启动任何新的线程。我创建了一个新队列,以逐行保存串行数据,作为主要传入数据处理程序。然后,我使用一个计时器将队列中的所有项目出列,并在我的列表框和标签中操作、格式化和显示它们。感谢那些插话的人!