2

私には 2 つのタスクがt1ありt2、次のように開始/終了非同期モデルで設計された古い API から生成します。しかし、私は厳密にそれらを次々に実行したいと思っています。(これは Azure テーブル ストレージ API です)

Task<DataServiceResponse> t1 = Task.Factory.FromAsync(ctx1.BeginSaveChangesWithRetries(null, null), r => ctx1.EndSaveChangesWithRetries(r));
Task<DataServiceResponse> t2 = Task.Factory.FromAsync(ctx2.BeginSaveChangesWithRetries(null, null),  r => ctx2.EndSaveChangesWithRetries(r));

await t1.ContinueWith(t => t2, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.NotOnCanceled);

ドキュメントを読みましたFromAsyncが、これらのタスク ( t1& t2) が起動されるかどうかは記載されていません。

FromAsync(IAsyncResult, Action<IAsyncResult>): 指定された IAsyncResult が完了したときにメソッド終了アクションを実行する Task を作成します。

  • の実行が成功した後、この保証t2は常に実行されますか?t1
  • このコードはBegin...、begin/end ペアのメソッドを呼び出していると思います。通常、操作 (この場合、Azure サービスへの HTTP 要求の作成) は end メソッドで行われますか? (begin/end 実装の内容についてはよくわかりません)
  • ステートメントの前に開始しますかt1(またはスケジュールされていますか)(私が使用するように)?awaitTask.Factory.StartNew
4

2 に答える 2

6

答えとして「いいえ、あなたが望むことはしません」よりも明確にするために:

Task.Factory.FromAsync は作成されたタスクを起動しますか?

はい、Taskオブジェクトは完全に機能しており、設計されたとおりに動作します-すでに実行中のリクエストが終了するのを待ちます。

これは、t1 の実行が成功した後に常に t2 が実行されることを保証しますか?

いいえ、Web リクエストは既に実行されています。または、それらを延期または注文するためのコントロールが不足しています。

によって作成されたタスクFormAsyncは、単独では開始できません。これらはパラメーターとして受け取るIAsyncResultため、 を呼び出して、基になるジョブ/タスク/Web 要求を既に開始していますBeginSaveChangesWithRetries。ここでのタスクは、この従来の非同期メカニズムのラッパーに過ぎず、それらを待機して、新しい適切な方法でコードを記述できるようにします。

良い方法でそれを行うには、次のように記述します。

await Task.Factory.FromAsync(ctx1.BeginSaveChangesWithRetries(null, null), r => ctx1.EndSaveChangesWithRetries(r));
await Task.Factory.FromAsync(ctx2.BeginSaveChangesWithRetries(null, null),  r => ctx2.EndSaveChangesWithRetries(r));

最初にスローを待機すると、2 番目は実行されません。

于 2013-07-23T07:27:31.313 に答える
1

タイトルの質問に対する答えはイエスです。Resharper の逆コンパイラと .NET 参照ソースを使用して見つかったように、新しいタスクが開始されますが、それは表示されません。

FromAsync は、内部で切り離された Task を作成して、その TaskScheduler で End メソッドを同期的に実行します。このタスクは表示されません。表示されるのは TaskCompletionSource.Task です。これは、End メソッドが正常に終了したとき、または例外をスローしたときに通知されます。

End メソッドによってスローされた例外は、TaskCompletionSource に設定されるため、待機する Task に設定されます。

FromAsync から返される Task は TaskCompletionSource によって作成されるため、開始されているかどうかはわかりません。操作が終了したときに待機して通知することができます。

そう:

T2 は正常に完了した場合にのみ実行されます

  1. T2 は、ContinueWith メソッドを呼び出す前に開始されるため、T1 と T2 は並行して実行されます。T2 は、T1 が成功した場合にのみ待機されます。
  2. Begin/End 内で何が起こるかは実装によって異なりますが、通常、Begin は非同期操作を開始し、End ブロックはこの操作の結果を待ちます。Web サービスと WebClient の呼び出しは、このように機能します。
  3. T1 は、最初の行で発生する Begin メソッドを呼び出すと開始します。

編集

IAsyncResult の代わりに関数を受け入れる FromAsync オーバーロードを呼び出しても、FromAsync はすぐに関数を呼び出して操作を開始するため、状況は変わりません。

于 2013-07-23T07:51:26.110 に答える