C # background worker - как запустить его для повторяющейся задачи - PullRequest
1 голос
/ 02 декабря 2011

Я получаю данные от последовательного порта, помещаю каждую строку в очередь, а затем удаляю строки из очереди, слегка форматирую их (удаляя некоторые начальные символы, обрезаю и т. Д.), А затем отображаю отформатированные строки в списке.

Я использую таймер для запуска метода снятия очереди каждые 200 мс.Все работает, но кажется, что это немного вяло / медленно.

Я рассматриваю возможность использования BackgroundWorker для обработки вывода в очередь и форматирования, но я застреваю.

Я пытался запустить backgroundworker в FormLoad, но быстро понял, что он будет проходить через код только один раз.Я попытался создать метку и перейти внутри кода фонового работника, чтобы создать цикл (я знаю, что это не хорошо), но это привело к высокой загрузке процессора и даже не сработало.

Я также попытался использовать "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 голосов
/ 03 декабря 2011

Я не вижу смысла разбирать вашу строку в другом потоке.это не длительная процедура, и, поскольку вы работаете в фоновом потоке, кажется, что вы забыли 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();
}
...