シリアルポートからデータを取得して処理し、UIに表示するアプリケーションをC#で開発しています。データは5〜50ミリ秒の速度で非常に高速に送信されます。スレッドを使用していなかった前。そのため、アプリケーションは、シリアルポートからデータを取得し、データを処理してUIに表示する単一のアプリスレッドに依存していました。そしてそれはいくつかのデータを失っていました。次に、BackgroundWorkerスレッドの実装を開始して、単一スレッドのオーバーヘッドを取り除き、優れたパフォーマンスを考えました。そして今、私は「このBackgroundWorkerは現在ビジーであり、複数のタスクを同時に実行することはできません「エラー。スレッドはシリアルポートからのデータの速度に対応できないと思います。そのため、「backgroundWorker1.RunWorkerAsync(data);」の実行時にエラーが発生します。このような種類を実装するためのより良いアプローチは何か提案が必要です。シナリオの?
7143 次
3 に答える
2
geofftnzは正しいので、少し拡張します。バックグラウンドワーカーは1回だけ起動し、ReportProgressを使用してデータをGUIスレッドにフィードバックする必要があります。ワーカースレッドは次のようになります。
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
}
}
GUIから、ProgressChangedイベントに登録し、ワーカーを1回だけ起動します。
于 2009-07-29T00:20:25.520 に答える
0
問題は、前の操作が完了する前に backgroundWorker1.RunWorkerAsync() を呼び出していることです。
おそらく必要なのは、シリアル ポートを読み取り、データをバッファリングし、データが利用可能であることをメイン UI スレッドに通知する単一のスレッドです。
于 2009-07-28T23:30:37.723 に答える
0
これを追加して、バックグラウンド ワーカーが一度に 1 つのジョブのみを実行するようにしてください。
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
}
于 2009-07-28T23:41:11.417 に答える