2

重複の可能性:
c# でタスクの開始を遅らせる正しい方法は何ですか?

将来実行される小さなタスクをスケジュールする必要があります (遅延は常に 1 分未満です)。実装は、.NET 4.0 ランタイムの .NET で行われます。Async ctp はオプションですが、今のところ付加価値はありません。

  • スケジューリングは非同期である必要があります
  • スケジューリングの解決は秒単位です
  • タスクの実行は暗黙的に非同期です(私は思います)
  • スケジュールされたタスクの数は数百または数千になる可能性があります
  • 可能性は低いですが、2 つのタスクがまったく同時にスケジュールされる可能性があります。

私の現在の解決策はこれです:

internal class TimerState
{
    internal Timer Timer { get; set; }
    internal object Payload { get; set; }
    internal Action<object> Action { get; set; }
}

public class TimerModule
{
    public static void ScheduleTask(object input, Action<object> action, TimeSpan delay)
    {
        //create state to pass to timer method
        var state = new TimerState { Payload = input, Action = action };

        //schedule timer without firing 
        var t = new Timer(HandleScheduleTimer, state, -1, -1);

        //add timer to state to be able to dispose it
        state.Timer = t;

        //schedule timer to fire in delay time
        t.Change(delay, TimeSpan.FromMilliseconds(-1));
    }


    private static void HandleScheduleTimer(object state)
    {
        var s = state as TimerState;

        Task.Factory.StartNew(s.Action, s.Payload, CancellationToken.None,
                              TaskCreationOptions.PreferFairness, TaskScheduler.Current);

        //dispose the timer immediately
        if(s.Timer != null)
            s.Timer.Dispose();
    }
}

パフォーマンス カウンター (.NET 物理スレッド) を使用していくつかのテストを行いましたが、ほぼ同時に数千のタスクをスケジュールしているにもかかわらず、同時に実行されているスレッドは多くありません。

これを行うより良い方法はありますか?

これに関する実証済みの設計パターンはありますか?

ほとんどの場合、再起動後もスケジューリングが信頼できることがわかりましたが、それは必要ありません。クラッシュ後にシステム内のデータを再生し、実行されなかったスケジュールされたタスクを補うことができます。

編集:何千ものスレッドが同時に実行されるのを見たいという意味ではありません。これはおそらくスレッドプールで処理されることを認識しています。コメントで述べたように、100 秒以上にわたる 5M タスクのテストでは、物理スレッドで 20 の増加しか見られません。

私の主な質問はこれです: タスクの実行を遅らせるより良い方法はありますか?

4

1 に答える 1

1

あなたが探しているソリューションはQuartzです。

http://quartznet.sourceforge.net/

これは、さまざまなスケジュールに関連付けられたさまざまなジョブを処理できる、非常に堅牢なスケジューラです。タイマーよりもはるかに信頼性があります。何か問題が発生した場合のフェイルオーバーがあります。

スケジュールは、CRON 間隔を使用するか、特定の日付に実行できます。インスタンスには何千ものジョブがあると聞いたことがあります。Quartz は必要に応じてクラスター化でき、ステートフル (以前のインスタンスの知識を保持) および非ステートフル ジョブを実行できます。構成方法に応じて、同時に実行することも、キューで実行することもできます。ほとんどのスレッドとスレッド セーフの問題は解決されており、頭を悩ませることなく自由にジョブ クラスを記述できます。

セットアップは簡単 (サービスのインストールと構成)​​ で、Quartz ジョブの作成はさらに簡単です。IJob から継承するクラスを作成し、ロジックを適用して、quartz 構成に追加します。構成は、xml ファイル、SQL サーバー データベース、または独自のソリューションを作成することができます。私は RavenDB 用に取り組んでいます。

于 2012-06-08T12:40:50.620 に答える