いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

.NET クラスライブラリ探訪-065 (System.IProgress, System.Progress, .NET 4.5から追加, 進捗状況, レポート)

今回は、System.IProgressとSystem.Progressクラスについてちょこっとメモメモ。


IProgressとProgressは、どちらも.NET Framework 4.5で追加された型です。
文字通り、進捗状況を処理するための型です。


IProgressインターフェースを実装したクラスがProgressとなります。
利用方法は、シンプルで

  • コンストラクタにActionデリゲートを渡して構築
  • ProgressChangedイベントをハンドル

することで、利用できます。


実際に進捗を処理するには、

IProgress<T>.Report(T)

メソッドを呼び出します。
GUIで、別の処理をしながら画面に進捗状況を出力する際に利用できます。
TaskとCancellationTokenとProgressを利用することで
以前から存在していたBackgroundWorkerと同じような事が実装できます。


Progressは、インスタンス構築時に現在のコンテキストに紐付いている
SynchronizationContextをキャプチャして保持します。Reportメソッド
内部でコールバックを実行する際に、キャプチャしたSynchronizationContext上で
そのメソッドを実行してくれます。なので、そのメソッドの中では、InvokeなしでUI要素にアクセスすることができます。


なので、Progressインスタンスを生成する場所が重要です。
UIスレッド上でnewしていないと、キャプチャされるSynchronizationContextが違うものになってしまいます。
このあたりの事情は、BackgroundWorkerの場合と同じですね。


SynchronizationContextについては、以前に記事をアップしていますのでご参照ください。


以下サンプルです。
なんか、いいサンプルが思いつかなかったので、とりあえずプログレスバーを更新するだけの
ものとなっています。ご勘弁をw


System.IProgress<T>のサンプル



実行すると、プログレスバーが更新されて伸びていき、MAXになったらまた元に戻り伸びていくを
繰り返します。ただし、CancellationTokenSourceをタイムアウト付きで設定しているので
設定したタイムアウト時間を超えたら、自動的にキャンセル扱いとなり、処理が終了します。


上記サンプルの中の

var progress = new Progress<int>(SetProgress);
//var progress2 = Task.Run(() => new Progress<int>(SetProgress)).Result;
await PerformStep(tokenSource.Token, progress);

となっている部分を、

//var progress = new Progress<int>(SetProgress);
var progress2 = Task.Run(() => new Progress<int>(SetProgress)).Result;
await PerformStep(tokenSource.Token, progress2);

に変えて、実行すると今度はプログレスバーが一切伸びないようになります。
Progressの生成をUIスレッドでは無い場所で行っているため、キャプチャされるSynchronizationContext
がDispatcherSynchronizationContextとならないからです。(この場合、ThreadPoolで実行されます。)


[追記]
なんか、サンプルがあまりにもショボイので、もう一つ作りましたw
こちらもショボイのですが、ちょっとマシかなと。


以下では、カレントフォルダの内容を1ファイルずつ圧縮して、1つのZipファイルを作成しています。
その際の進捗状況の処理にProgressを利用しています。キャンセルができるようになっていて
処理途中でキャンセルされたら、簡易ロールバック処理をしています。


ZipFileクラスの概要については、以下の記事をご参照ください。



System.IProgress<T>のサンプル2

そのままだと、処理がすぐに終わってしまうので、わざとTask.Delayを入れています。



以下、参考資料です。正直、機械翻訳の日本語が若干変なので原文読んだ方がわかりやすいと思います。

================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。