42

私はC#5の新しいasync/awaitキーワードにまったく慣れておらず、進行状況イベントを実装するための最良の方法に興味があります。

今、私はProgressイベントTask<>自体があった場合にそれを好むでしょう。非同期メソッドを含むクラスにイベントを配置し、イベントハンドラーである種の状態オブジェクトを渡すことができることはわかっていますが、それは解決策というよりも回避策のように思えます。また、さまざまなタスクでさまざまなオブジェクトのイベントハンドラーを起動したい場合もありますが、これはこのように厄介に聞こえます。

次のようなことをする方法はありますか?:

var task = scanner.PerformScanAsync();
task.ProgressUpdate += scanner_ProgressUpdate;
return await task;
4

4 に答える 4

61

推奨されるアプローチは、タスクベースの非同期パターンのドキュメントで説明されており、各非同期メソッドに独自のIProgress<T>.

public async Task PerformScanAsync(IProgress<MyScanProgress> progress)
{
  ...
  if (progress != null)
    progress.Report(new MyScanProgress(...));
}

使用法:

var progress = new Progress<MyScanProgress>();
progress.ProgressChanged += ...
PerformScanAsync(progress);

ノート:

  1. 慣例により、progressパラメーターはnull、呼び出し元が進行状況レポートを必要としない場合に使用される可能性があるため、メソッドでこれを確認してくださいasync
  2. 進行状況のレポート自体は非同期であるため、呼び出すたびに引数の新しいインスタンスを作成する必要があります (さらに良いのは、イベント引数に不変型を使用することです)。を複数回呼び出すために、同じ引数オブジェクトを変更して再利用しないでくださいProgress
  3. Progress<T>型は、構築時に現在のコンテキスト (UI コンテキストなど) をキャプチャし、そのProgressChangedコンテキストでイベントを発生させます。そのため、 を呼び出す前に UI スレッドに戻すマーシャリングについて心配する必要はありませんReport
于 2013-03-14T11:39:22.020 に答える
49

簡単に言えば、進歩をサポートTask しません。ただし、インターフェイスを使用して、これを行う従来の方法が既にありIProgress<T>ます。タスクベースの非同期パターンは基本的に、クライアントが実装を渡すことができるように、非同期メソッドをオーバーロードすることを (それが理にかなっている場合) 提案しますIProgress<T>。非同期メソッドは、それを介して進行状況を報告します。

Windows ランタイム (WinRT) APIにIAsyncOperationWithProgress<TResult, TProgress>、および型にプログレス インジケーターが組み込まれていIAsyncActionWithProgress<TProgress>ます。そのため、実際に WinRT 用に記述している場合は、それらを調べる価値がありますが、以下のコメントもお読みください。

于 2013-03-14T11:39:05.217 に答える
10
于 2014-11-06T16:22:38.633 に答える