8

バックグラウンドで実行したいアクションがいくつかありますが、それらは次々と同期的に実行する必要があります。

これを実現するために Task.ContinueWith メソッドを使用するのは良い考えかどうか疑問に思っていました。これに何か問題があると思いますか?

私のコードは次のようになります。

private object syncRoot =new object();
private Task latestTask;

public void EnqueueAction(System.Action action)
{
    lock (syncRoot)
    {
        if (latestTask == null)
            latestTask = Task.Factory.StartNew(action);
        else
            latestTask = latestTask.ContinueWith(tsk => action());
    }
}
4

3 に答える 3

9

これには 1 つの欠陥があります。これは、タスクが順次実行されるようにするこの方法も使用しているため、最近発見したものです。

私のアプリケーションには、これらのミニキューのインスタンスが何千もあり、すぐにメモリの問題があることに気付きました。これらのキューはしばしばアイドル状態だったので、最後に完了したタスク オブジェクトを長時間保持し、ガベージ コレクションを妨げていました。最後に完了したタスクの結果オブジェクトはしばしば 85,000 バイトを超えるため、大きなオブジェクト ヒープ (ガベージ コレクション中に圧縮を実行しません) に割り当てられました。これにより、LOH が断片化され、プロセスのサイズが継続的に拡大しました。

これを回避するためのハックとして、ロック内の実際のタスクの直後に何もしないタスクをスケジュールできます。実際の解決策として、スケジューリングを制御する別の方法に移行する必要があります。

于 2012-07-13T21:44:39.473 に答える
5

これは設計どおりに機能するはずです (対応するタスクが既に完了している場合、TPL はすぐに継続をスケジュールするという事実を使用します)。

個人的には、この場合、コンカレント キュー ( ) を使用して専用スレッドを使用してConcurrentQueueタスクを描画します。これはより明示的ですが、特に、現在キューに入れられているタスクの数などを知りたい場合は、コードの読み取りを解析する方が簡単です。

于 2011-07-21T17:31:55.717 に答える
0

私はこのスニペットを使用しましたが、設計どおりに動作するようです。私の場合のインスタンス数は数千ではなく、1 桁です。それにもかかわらず、これまでのところ問題はありません。

ConcurrentQueue の例があれば興味がありますか?

ありがとう

于 2014-05-09T15:21:10.613 に答える