1

次のように動作するキーを使用してタスクを実装するための最良のアプローチは何ですか?

オプション 1) このキーの 1 つだけが保留中です。たとえば、ASP.NET MVC から使用して、画像の URL が何回ヒットしても、サムネイル画像の単一のレンダリングをキューに入れることができます。1 つのみが実行され、他のすべての要求はその要求が完了するまで待機します。

オプション 2) 同じキーを持つすべての項目を順番に実行する必要があります。たとえば、バッキング ストアからローカル キャッシュにファイルをフェッチする操作がすべて同時にファイルをキャッシュに取得しようとしないようにするために使用できます。オプション 1 は、同じキーを持つ後続のアクションが単純に破棄される特殊なケースです (通常、ファイルの存在チェックのみを保存します)。

これらのケースの両方を処理する既存の WorkQueue があります (アパートメント状態、ThreadPriority 設定、および最大並列度も同様です)。TPL は、これを置き換えるための最良のソリューションと思われ、改善されたキャンセル オプションを提供します。

継続を伴うネストされたタスクは有望に見えますが、現在キューに入れられているタスクのディクショナリを維持することはすぐに、TaskFactory クラスと TaskScheduler クラスの間で面倒になります。TaskFactory も TaskScheduler も Task ではジェネリックではないため、Task からの継承にも問題があります。

ほとんどのタスク並列の例では、一連のタスクが事前にわかっていることを前提としています。この場合、新しいタスクが常に追加され、要求された操作と渡されたキーに応じて、破棄するか、既存のタスクにチェーンする必要があります。

TPL を使用してこれに似たものを実装した人はいますか? もしそうなら、Task、TaskScheduler、および TaskFactory クラスでどのようなアプローチを取りましたか?

4

2 に答える 2

1

この問題は、 ReactiveXamlで解決した問題と似ていますが、以前のリクエストもメモ化しています。QueuedAsyncMRUCacheのコード(およびそのブログエントリ)を見てください-このコードはTPLとReactive Extensionsを組み合わせてこの種のことを実行しますが、同じキーに対する2番目のリクエストがブロックされることを重要な保証にします別のリクエストを発行する代わりに、最初の実行中のリクエスト。

于 2010-08-31T23:13:49.057 に答える
1

おそらく、私が考えることができる1つの方法は

  1. ラッパー クラスを作成します。KeyProcessor と言って、キーのアイテムをキューに入れます。
  2. KeyProcessor.Run() メソッドは、必要なキューイング セマンティクスに対応します。基本的に、保留中の作業の内部キューを探し、それを順番に実行し続けます。
  3. KeyProcessor オブジェクトのディクショナリを維持します。
  4. 新しいタスクについては、辞書で同じキーを確認してください。存在しない場合は追加します。タスクをキューに入れます。実行されていない場合は、Run メソッドをアクションとして使用して TPL でスケジュールします。
  5. ContinueWith を使用してメンテナー タスクをスケジュールします。たとえば、KeyProcessor.Run を実行するタスクが完了するたびに、継続タスクは、同じキーに対してスケジュールされているタスクが他にあるかどうかを確認し (完了したため)、再度開始するか、辞書から削除します。

上記のすべては、 System.Collections.Concurrent名前空間に存在するいくつかの興味深いコレクションではなく、スレッド同期ポイントから注意が必要です。これにより、上記のロジックがはるかに単純になります。たとえば、ConcurrentDictionary.GetOrAddを使用すると、スレッドセーフな方法で KeyProcessor オブジェクトを検索および/または追加できます。

于 2010-09-01T06:18:50.947 に答える