2009-07-28 15 views
2

C#でシリアルポートからデータを取得し、処理してUIに表示するアプリケーションを開発中です。 データは5〜50msの速度で非常に高速になります。私がスレッドを使用していないうちにアプリケーションがシリアルポートからデータを取得していた単一のアプリケーションスレッドに依存していたため、データを処理してUIに表示していました。いくつかのデータが失われていました。 その後、私はBackgroundWorkerスレッドを実装して、シングルスレッドのオーバーヘッドを取り除き、優れたパフォーマンスを考え始めました。そして、今私は "このBackgroundWorkerは現在ビジー状態であり、複数のタスクを同時に実行することはできません"というエラーが発生しました。私はスレッドがシリアルポートから来るデータの速度に対応することができないと思う。 "backgroundWorker1.RunWorkerAsync(data);"を実行するとエラーが発生します。私はこのような種類のシナリオを実装するためのよりよいアプローチが何か提案を必要としていますか?シリアルポートのデータ処理に使用されるスレッド「このBackgroundWorkerは現在ビジー状態であり、複数のタスクを同時に実行できません」

+0

この回答は適用されますか? http://stackoverflow.com/questions/588150/c-this-backgroundworker-is-currently-busy-and-cannot-run-multiple-tasks-concurre/588158 –

+0

100%ではありませんが、これらのすべてから道がありますコメントをサポートし、私は問題を解決することができます。お返事ありがとう –

答えて

0

問題は、以前の操作が終了する前にbackgroundWorker1.RunWorkerAsync()を呼び出していることです。

おそらく、シリアルポートを読み取ってデータをバッファリングし、メインUIスレッドにデータが利用可能であることを通知する単一のスレッドが必要です。

+0

ありがとうございました。 シリアルポートからのデータの読み取り、データのバッファリング、UIへの通知に、単一バックグラウンドワーカースレッドを使用しています。私はbackgroundWorker1_RunWorkerCompletedイベントは有効な出力があることを通知すると思うif(e.Result!= null){}私は間違っている場合、UIスレッドを修正します。 - Chetan –

+0

Mirozellの答えを確認してください:) – geofftnz

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 
    } 
+0

私はすでにこれを追加しましたが、このスレッドではデータが処理されず、UIには向いていないときにデータが失われています。 –

+0

私はアプローチデータが絶えず流れるようにしています。 –

+0

あなたの最善の策は、これらの*一般的な*バックグラウンドの裏にあるデータを処理するために使用され、UIが依然として応答している間、定期的にUIを更新するので、単一のbackgroundWorkerの代わりにスレッドプールを使用することです。 – PostMan

2

geofftnzが正しいコードサンプルであり、私はあなたのためにビットを拡張します。バックグラウンドワーカーは一度起動し、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回だけ起動します。

+0

ありがとうMirozell、 roの値を確認してUIに自分のデータを送るメソッドを呼び出しています。しかし、それはどういうわけかこの関数を適切に処理していません。私がその機能をデバッグしているとき、それを正しくデバッグして前後にジャンプすることはできません。ここで何が起こっているのか分かりません。 –

+0

Visual Studioはブレークポイントにヒットしたスレッドに自動的にジャンプします。 'Show threads in source'をオンにすると、他のスレッドがどこにあるのかを示す小さな指標が得られます。あなたのケースで最も簡単なのはおそらく、GUIスレッドのデバッグ中にワーカーのブレークポイントを削除/無効にすることです。逆もまた同様です。 – Mirozell

+0

私はこれを解決することができます。私がやっているのは、シリアルポートから得たデータです。これをキューに追加しています。 Busy状態をチェックしてBackgroundWorkerスレッドを使用してQueueをDequeingしています。とにかく例外はありません。あなたのおかげで、私をサポートするのに時間を費やしてくれました。 –

関連する問題