ファイル I/O の進行状況を報告するために使用するプログレスバーとキャンセル ボタンがある ProgressBarWindow があります。ただし、バックグラウンドワーカーですべての作業が行われているにもかかわらず、ProgressBarWindow の UI スレッドとメイン ウィンドウの両方がハングします。プログレスバーは、メイン ウィンドウと同様にレンダリングされますが、バックグラウンド ワーカーが作業を行っている間は更新されません。次のコードは、メイン ウィンドウのコンストラクターの最後で呼び出されます。
iCountLogLinesProgressBar = new ProgressBarWindow();
iCountLogLinesProgressBar.cancelButton.Click += EventCountLogLinesProgressBarCancelButtonClicked;
iCountLogLinesProgressBar.Show();
iCountLogRecords = new BackgroundWorker();
iCountLogRecords.DoWork += EventCountLogLinesDoWork;
iCountLogRecords.ProgressChanged += EventCountLogLinesProgressChanged;
iCountLogRecords.RunWorkerCompleted += EventCountLogLinesRunWorkerCompleted;
iCountLogRecords.WorkerReportsProgress = true;
iCountLogRecords.WorkerSupportsCancellation = true;
iCountLogRecords.RunWorkerAsync(new BinaryReader(File.Open(iMainLogFilename, FileMode.Open, FileAccess.Read)));
EventCountLogLinesProgressChanged() は次のようになります。
private void EventCountLogLinesProgressChanged(object sender, ProgressChangedEventArgs e)
{
iCountLogLinesProgressBar.Value = e.ProgressPercentage;
}
これは ProgressBarWindow の短縮版です (残りはセッターの数だけです):
public partial class ProgressBarWindow : Window
{
public ProgressBarWindow()
{
InitializeComponent();
this.progressBar.Value = this.progressBar.Minimum = 0;
this.progressBar.Maximum = 100;
}
public double Value
{
get
{
return progressBar.Value;
}
set
{
this.progressBar.Value = value;
}
}
}
値セッター行をdispatcher.invokeデリゲートでラップしようとしましたが、スタックオーバーフローが発生します(backgroundworkerがUI ThreadでProgressChangedを呼び出すので、dispatcher.invoke行を持つ必要はありませんよね?)。私はmsdnとgoogledをチェックしましたが、この問題を抱えている人を他に見つけることができないようです.
編集申し訳ありませんが、単純化したコードが UI スレッドをブロックしていることに気付きませんでした。バックグラウンドワーカーを使用しているにもかかわらず、まったく同じ動作が得られるため、それらが同等であると誤って想定しました。バックグラウンドワーカーを使用していたことに言及する必要がありました:P