.NET 4中的任务调度程序设计(任务并行库)

时间:2011-03-22 11:51:13

标签: .net scheduling task-parallel-library

我正在尝试创建一个使用TPL以异步(并行)方式执行计划任务的服务。

基本要求是,对于一系列不同的任务,每个任务都有自己的预定速率(一些要每秒执行一次,另外30秒,其他5分钟等)要同时执行。而且我不确定最好的解决方法,特别是考虑到ConcurrentBag(我考虑将其作为所有未来任务的持有者)不包含用于选择需要执行的任务集合的方法。

这也意味着我不能使用WaitAny或WaitAll,因为这些短期运行的任务需要独立完成并重新排队。

我该如何处理?

编辑:

好的,基本上我的设计是这样的:

ScheduledTask,它是具有Scheduled DateTime属性的Task的包装器。其中一堆存储在ConcurrentBag

一个控制器,它轮询ConcurrentBag(当前只是一个while(true)循环,但可能是一个Timer或类似的东西),删除任何已调度的,以及Start()的它们。

每个ScheduledTask都包含对ConcurrentBag的引用,并在完成时使用新的ScheduledTime将自身的新实例排入队列。

到目前为止,这个设计似乎有效,但是每个Task都有一些东西,它们对ConcurrentBag的引用并不适合我。任何设计意见或建议将不胜感激。

4 个答案:

答案 0 :(得分:2)

您是否考虑过使用RX的EventLoopScheduler?

Rx有许多不同的调度程序实现,但EventLoopScheduler听起来像是适合你的。

要使用RX创建重复任务,您只需使用Observable.Interval(timespan, scheduler).Subscribe(action)

答案 1 :(得分:1)

由于您需要删除特定项目,因此无法使用concurrentbag。

一种方法是让每个任务看起来像

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

调度程序看起来像

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);
                                                  });
}

答案 2 :(得分:1)

如果您不想自己动手,可以使用http://quartznet.sourceforge.net/

答案 3 :(得分:0)

我使用线程池(不是TPL)为学校项目编写了一个同步任务调度程序。我从来没有让它变得异步;您可以在单独的后台线程上运行任务,并让它执行回调委托。 See here on SourceForge.