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

时间:2011-12-01 22:14:32

标签: c# backgroundworker deque

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

我使用Timer每隔200ms触发一次Dequeuing方法。一切正常,但似乎有点迟缓/缓慢。

我正在考虑使用BackgroundWorker来处理排队和格式化但是我遇到了问题。

我尝试在FormLoad中启动backgroundworker,但很快意识到它只会运行一次代码。我尝试了一个标签并在后台工作代码中转到创建一个循环(我知道,不是很好),但这让我的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);
}

1 个答案:

答案 0 :(得分:0)

我没有看到在不同的线程中解析你的字符串的观点。它不是一个长时间运行的过程,并且由于您在后台线程中运行,似乎您忘记了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();
}