11

.NET 4.5 および Async CTP 4.0 のawaitを含むフローは、リモート クライアントが応答しないなど、さまざまな理由でスタックする可能性があります。もちろん、一部のタイムアウト タスクも待機する WaitForAny は、高レベル フローを回復するための明らかなソリューションです。それでも、これですべての問題が解決するわけではありません。

次の質問があります。

  1. 戻らないawaitのコンテキストはどうなりますか? これによりメモリリークが発生することを理解しています。私は正しいですか?

  2. デバッガーで、またはそれぞれの API を使用して、アプリケーションにぶら下がっている「awaiter」がいくつ存在するかを確認するにはどうすればよいですか?

  3. それらをグローバルに列挙することは可能ですか?

  4. 3. が正しい場合、これらの*await * のタスクを強制的にキャンセルする (つまり、クリーンアップする) ことは可能ですか?

注: 質問 4 では、明示的なタスクの作成中に使用されるキャンセル項目については質問しません。タスクが間接的に作成された場合を意味します。

async Task<bool> SomeTask()
{
   await Something();
   ...
   return true;
}

この質問の動機:

  1. メモリリークを回避しようとしています
  2. キャンセルトークンを含むケースが多すぎてコードを複雑にしようとしています
  3. 多くの場合、各低レベル タスクのタイムアウトは事前にわかりませんが、高レベル フローでは回復アプローチのみを使用できます。
4

2 に答える 2

9

1 二度と戻らない await のコンテキストはどうなりますか?

メモリ リークが発生すると思います ( awaitI/O 操作を行っている場合)。常にsを完了するTaskのが最善です(これは、async遅かれ早かれ常にメソッドが返されることを意味します)。

svick のコメントからの更新:これによりメモリ リークが発生しない場合があります。

2 デバッガーまたはそれぞれの API を使用して、アプリケーション内にいくつのぶら下がっている "awaiter" が存在するかを確認するにはどうすればよいですか?

これを行う簡単な方法があるかどうかはわかりません。SoSを使用して、コンパイラによって生成された非同期ステート マシンのパターンに一致する既存のヒープ オブジェクトを見つけるデバッガー プラグインを作成できるはずです。

しかし、それはほとんど利益のない多くの作業です。

3 それらをグローバルに列挙することは可能ですか?

通常の API ではありません。

3 が正しい場合、これらの待機中のタスクを強制的にキャンセルすること (つまり、クリーンアップすること) は可能ですか?

実行時に (たとえば、プロファイリング API を介して) それらを列挙できたとしても、タスクの取り消しを「強制」することはできません。キャンセルは協力的です。


これに対処する正しい方法は、標準のキャンセルです。タスクベースの非同期パターン ドキュメントでは、キャンセル可能なメソッドのガイドラインが指定されていasyncます。

最低レベル: asyncBCL の多くの API は、オプションのCancellationToken.

中間レベル:asyncメソッドにオプションを持たせ、それを他のメソッドCancellationTokenに渡すのが一般的です。async

最上位レベル:一定時間後に起動する を簡単に作成できます。CancellationToken

于 2012-10-18T13:55:39.800 に答える
2

質問2と3について私には本当の答えはありません。

  1. アプリケーションの終了時にCLRがタスクを破棄するときに、タスクで使用されるリソースが適切に破棄される限り、私はそれを疑っています。

決して戻らないタスクを回避することは、決して良いことではありません。これを回避し、ポイント4に答えるには、タスクをキャンセルできます。

タスクに渡すキャンセルトークンを作成する必要があります。タスクは、そのキャンセルトークンのステータスを監視し、キャンセルされたときに例外をスローする責任があります。(同じトークンを使用して、複数のタスクを一度にキャンセルすることもできます。)

MSDNのこの記事は、そうすることを示しています。

于 2012-10-18T12:07:52.587 に答える