开发者

Design for task scheduler in .NET 4 (Task Parallel Library)

开发者 https://www.devze.com 2023-02-18 04:24 出处:网络
I\'m trying to create a service that executes scheduled Tasks in an asynchronous (and parallel) way using TPL.

I'm trying to create a service that executes scheduled Tasks in an asynchronous (and parallel) way using TPL.

The basic requirement is that for a bunch of different tasks, each with their own scheduled rates (some to be executed every second, others 30 seconds, other 5 mins etc) to be executed concurrently. And I'm not sure of the best way to go about this, especially considering the ConcurrentBag (which I was considering as a holder of all future tasks) contains no methods with which to select collections of tasks that need to be executed.

It also means that I can't use WaitAny or WaitAll, 开发者_开发百科as these short-running tasks need to finish and requeue themselves independently.

How should I proceed with this?

Edit:

Ok basically my design is thus:

A ScheduledTask, which is a wrapper for Task with a Scheduled DateTime property. A bunch of these are stored in a ConcurrentBag

A Controller that polls the ConcurrentBag (currently just a while(true) loop, but could be a Timer or similar), removing any that are scheduled, and Start()'s them.

Each ScheduledTask holds a reference to the ConcurrentBag, and enqueues a new instance of itself when it completes, with a new ScheduledTime.

This design seems to work so far, but there is something about each Task holding a reference to the ConcurrentBag that doesn't sit well with me. Any design comments or suggestions would be appreciated.


Have you considered using the EventLoopScheduler from RX?

Rx has lots of different scheduler implementations, but EventLoopScheduler sounds like the right one for you.

To create a repeating task with RX, you'd just use Observable.Interval(timespan, scheduler).Subscribe(action).


You can't use a concurrentbag since you need to remove specific items.

One way to do it is to let each task look like

MyTask SomeAction() {
    DateTime now = DateTime.Now;
    DoSomeTask();
    return new MyTask { StartTime = now.AddMinutes(1), DoSomething = SomeAction }
}

the scheduler will look something like

List<MyTask> tasklist = new List<MyTask>();

public void Scheduler() {
    for (;;)
        DateTime now = DateTime.Now;

        List<MyTask> tasksToRun;
        lock (taskList) 
            taskToRun = taskList.Where(x => x.StartTime <= now)
                                .ToList();

        var tasks = tasksToRun.Select(x => RunTask(x))
                              .ToArray();
        Thread.Sleep(1000);
    }
}

private Task<MyTask> RunTask(MyTask myTask) {
    lock (taskList)
        tasklist.Remove(myTask);

    return Task<MyTask>.Factory.StartNew(myTask.DoSomething())
                               .ContinueWith(t => {
                                                      if (t.Result != null)
                                                          lock (taskList)
                                                              taskList.Add(t.Result);
                                                  });
}


You could use http://quartznet.sourceforge.net/ if you do not want to do it by yourself.


I wrote a synchronous task scheduler for a school project using the thread pool (not TPL though). I never got around to making it async; you could run the tasks on a separate background thread and have it execute a callback delegate. See here on SourceForge.

0

精彩评论

暂无评论...
验证码 换一张
取 消