2016-03-27 7 views
0

かなり長い時間を要するアクションを実行する必要がある場合、このようなBackgroundWorkerで呼び出すため、UIはフリーズしません。バックグラウンドワーカーを使用してUIを更新する

BackgroundWorker bgWorker = new BackgroundWorker(); 

bgWorker.DoWork += (s, e) => { 
    //Do something long lasting 
    for(int i = 0; i < x; i++){ 

     //Performing action i of x 

     //While doing so update the progressbar 
     prgBar.Dispatcher.Invoke(() =>{ 
      prgBar.Value += ((i/x) * 100.0); 
     }); 

    } 
}; 

bgWorker.RunWorkerCompleted += (s, e) => { 
    //Finish up things 
}; 
bgWorker.RunWorkerAsync(); 

これはUIを更新するための「行く方法」ですか、「されていません」ですか? BackgroundWorkerにも同じ質問が適用されます(BackgroundWorkerの代わりに新しいスレッドを開始することは可能でしょうか)。

+1

:だから、単にその後、プログレスバー、フォーム上のコントロールとを持つことができます方法。 –

答えて

3

バックグラウンドスレッドからUIコンポーネントを更新する必要がある場合は、メインスレッドへの呼び出しをマーシャリングするためにDispatcherを使用する必要があります。これは、いくつかの進行状況バーを更新しようとしているようだと言われています。 BackgroundWorkerクラスは、すでにそのためのメカニズムを提供しています。私はちょうどあなたがあるため、バックグラウンドタスクの凍結せずにUIを更新したい場合は、通常の方法は、今日非同期のawaitであることに注意したい

var bgWorker = new BackgroundWorker(); 

// Specify that this worker supports progress 
bgWorker.WorkerReportsProgress = true; 

bgWorker.OnProgressChanged += e => 
{ 
    // This is called on the main thread. It safe to update your UI components here 
    myProgressBar.Value = e.ProgressPercentage; 
}; 

bgWorker.DoWork += (s, e) => 
{ 
    // Do something long lasting 
    for(int i = 0; i < x; i++) { 
     //Performing action i of x 

     // While doing so notify the subscribers of the progress event 
     var progress = (int)((i/x) * 100.0); 
     bgWorker.ReportProgress(progress); 
    } 
}; 

bgWorker.RunWorkerCompleted += (s, e) => 
{ 
    //Finish up things 
}; 

bgWorker.RunWorkerAsync(); 
1

いいえ、そうではありません。主な問題はプログレスバーです。UIスレッドではなく、バックグラウンドのワーカースレッドに割り当てられています。それは本当に何にもぶら下がっていることはありません - それはどこに表示されていますか?

適切な方法は、進行状況バーを含むフォームを用意し、バックグラウンドワーカーを開始する前にUIスレッドで開くか、ちょうどショットを開始し、完了したら非表示にします。

Dispatcherの更新ロジックは、現時点で正しく初期化されていないプログレスバーに当たっても「正しい」です。しかし、あなたは何をしなければならないのですか?

関連する問題