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