如何延迟' hot'任务,以便按订单顺序处理

时间:2016-10-19 10:32:43

标签: c# asynchronous async-await task-parallel-library task

说我有一系列任务:

        var task1 = DoThisAsync(...);
        var task2 = DoThatAsync(...);
        var task3 = DoOtherAsync(...);
        var taskN...

我正在寻找一种方法来按顺序处理一组任务(由包含集合中的位置确定),但让任务只在轮到而不是之前运行/启动 - 并且包含所有这些任务完成自己的任务。

问题限制/细节是:

  1. 这些任务需要按特定顺序执行,即任务1,任务2,......
  2. 上一个任务必须在下一个任务开始之前异步完成
  3. 任务数量可变
  4. 每次运行代码时都可以指定一组不同的任务
  5. 事先知道任务的顺序和数量。
  6. 主要问题是,只要我调用相关方法(如DoThis()...)来返回每个任务,该任务就已经很热了。或跑步,违反上述(2)。

    我尝试过.ContinueWith(..),但是如果我调用上面的每个任务来设置延续或将它们添加到列表或集合中,那么它们已经开始了。

    不确定Lazy< T>可能有所帮助,但现在看不出来怎么样?

    希望这是有道理的,因为我对async / await / tasks很新。

    非常感谢提前。

2 个答案:

答案 0 :(得分:7)

调用方法运行代码。如果您想要一个稍后将调用此方法的对象,请使用委托。

在这种情况下,您可以使用Func<Task>,这是一个异步委托。这些列表应该足够了:

// Build the list of operations in order.
var operations = new List<Func<Task>>();
operations.Add(() => DoThisAsync(...));
operations.Add(() => DoThatAsync(...));
operations.Add(() => DoOtherAsync(...));

// Execute them all one at a time.
foreach (var operation in operations)
  await operation();

答案 1 :(得分:-1)

您只需使用其构造函数创建任务,然后使用.Start()方法调用执行。

这是一个例子:

var taskList = InitQueue();
foreach (var t in taskList.OrderBy(i => i.Order))
{
    //Here I can skedule an existing task
    t.TaskToRun.Start();
    t.TaskToRun.Wait();
    Console.WriteLine($"Task {t.Order} has finished its job");
}


public class TaskQueue : List<TaskItem>
{
}

public class TaskItem
{
    public int Order { get; set; }
    public Task TaskToRun { get; set; }
}

private static TaskQueue InitQueue()
{
    var queue = new TaskQueue();
    queue.Add(new TaskItem
    {
        Order = 1,
        TaskToRun = new Task(() =>
        {
            Task.Delay(500);
            Console.WriteLine("Hello from task 1");
        })
    });
    queue.Add(new TaskItem
    {
        Order = 4,
        TaskToRun = new Task(() => Console.WriteLine("Hello from task 4"))
    });
    queue.Add(new TaskItem
    {
        Order = 3,
        TaskToRun = new Task(() =>
        {
            Task.Delay(5000);
            Console.WriteLine("Hello from task 3");
        })
    });
    queue.Add(new TaskItem
    {
        Order = 2,
        TaskToRun = new Task(() => Console.WriteLine("Hello from task 2"))
    });

    return queue;
}