Поток, используемый для обработки данных последовательного порта «Этот BackgroundWorker в настоящее время занят и не может одновременно выполнять несколько задач»

2

Я разрабатываю приложение на С#, которое получает данные из последовательного порта, обрабатывает его и показывает его в пользовательском интерфейсе. Данные поступают очень быстро между 5-50 мс скоростью. Прежде чем я не использовал нити. и поэтому приложение полагалось на один поток приложений, который получал данные из последовательного порта, обрабатывал данные и показывал их в пользовательском интерфейсе. и это потеряло некоторые данные. Затем я начал внедрять поток BackgroundWorker, чтобы удалить некоторые накладные расходы в одном потоке и думать о хорошей производительности. И теперь я получаю " Этот BackgroundWorker в настоящее время занят и не может выполнять несколько задач одновременно". Я думаю, что Thread не может справиться со скоростью данных, поступающих из последовательного порта. и поэтому бросать ошибку при выполнении "backgroundWorker1.RunWorkerAsync(data);". Мне нужно несколько советов, какой лучший подход к реализации такого сценария?

  • 0
    Применим ли этот ответ? stackoverflow.com/questions/588150/...
  • 0
    Не на 100%, но я получил ответ от всех этих комментариев поддержки, и я могу решить эту проблему. Спасибо
Теги:
multithreading
serial-port
backgroundworker

3 ответа

2

geofftnz верен, и я немного расширю вас. Вы должны только запустить фоновый рабочий один раз, и попросите его вернуть данные в поток GUI с помощью ReportProgress. рабочий поток будет выглядеть примерно так.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackGroundWorker;
    while(!e.CancellationPending)
    {
        ResultObject ro = new ResultObject();  // your own type here, obviously
        //Process and store some data in ro;
        worker.ReportProgress(0, ro);
        //Do not modify ro after reporting progress to avoid threading issues
    }
}

В графическом интерфейсе зарегистрируйтесь в событии ProgressChanged и только один раз запустите работника.

  • 0
    Спасибо Mirozell, вот что я вызываю метод, который отправляет мои данные в пользовательский интерфейс, проверяя значение ro Passed. но это как-то не обрабатывает эту функцию должным образом. и когда я отлаживаю функцию, она не позволяет мне отладить ее должным образом и прыгать туда-сюда. Не знаю, что здесь происходит.
  • 0
    Visual Studio автоматически переключит вас на любой поток, который достигнет точки останова. Если вы включите «Показывать потоки в источнике», вы получите небольшой индикатор того, где находятся другие потоки. В вашем случае проще всего, вероятно, удалить / отключить точки останова на рабочем месте при отладке потока графического интерфейса и наоборот.
Показать ещё 1 комментарий
0

Попробуйте добавить это, чтобы убедиться, что фоновый рабочий работает только за одно задание за раз.

if(!backgroundWorker1.IsBusy)
    backgroundWorker1.RunWorkerAysnc();

У вас также есть возможность отменить текущее задание, вот пример кода

    private void WhereBackworkerStarts()
    {
        backgroundWorker.WorkerSupportsCancellation = true;

        if (backgroundWorker.IsBusy)
            backgroundWorker.CancelAsync();
        else
            backgroundWorker.RunWorkerAsync();
    }

    // Events
    static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        for(int i = 0; i < int.MaxValue; i++)
        {
            if (backgroundWorker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            // Do work here
        }
        e.Result = MyResult;
    }

    static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Deal with results
    }
  • 0
    Я уже добавил это, но в этом случае я теряю некоторые данные, когда этот поток занят, я имею в виду, что данные не обрабатываются и не собираются в пользовательский интерфейс.
  • 0
    Я ищу подход, данные должны быть непрерывно текущими.
Показать ещё 7 комментариев
0

Проблема в том, что вы вызываете backgroundWorker1.RunWorkerAsync(), прежде чем закончите с предыдущей операцией.

То, что вы, вероятно, хотите иметь, это один поток, который считывает последовательный порт, буферизует данные и уведомляет об этом основной поток пользовательского интерфейса.

  • 0
    Спасибо за быстрый ответ. Я использую поток Single Background Worker для чтения данных из последовательного порта, буферизации данных и уведомления пользовательского интерфейса. Я думаю, что событие backgroundWorker1_RunWorkerCompleted уведомит, что есть корректный вывод через поток (e.Result! = Null) {} в поток пользовательского интерфейса, исправьте меня, если я ошибаюсь. - Четан
  • 0
    Проверьте ответ Мирозелла :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню