【问题标题】:.NET Framework 4.0: Chaining tasks in a loop.NET Framework 4.0:循环链接任务
【发布时间】:2011-03-30 12:34:54
【问题描述】:

我想链接多个Tasks,这样当一个结束时下一个开始。我知道我可以使用ContinueWith 做到这一点。但是如果我有大量的任务怎么办,那么:

t1 继续 t2

t2 继续 t3

t3 继续 t4

...

除了使用循环手动创建此链之外,还有什么好的方法吗?

【问题讨论】:

  • 你能发布代码来展示你将如何使用 ContinueWith 吗?这可能会引发更多反馈。

标签: c# .net c#-4.0 parallel-processing task


【解决方案1】:

好吧,假设您有某种可枚举的 Action 代表或您想做的事情,您可以轻松地使用 LINQ 执行以下操作:

// Create the base task.  Run synchronously.
var task = new Task(() => { });
task.RunSynchronously();

// Chain them all together.
var query = 
    // For each action
    from action in actions

    // Assign the task to the continuation and
    // return that.
    select (task = task.ContinueWith(action));

// Get the last task to wait on.
// Note that this cannot be changed to "Last"
// because the actions enumeration could have no
// elements, meaning that Last would throw.
// That means task can be null, so a check
// would have to be performed on it before
// waiting on it (unless you are assured that
// there are items in the action enumeration).
task = query.LastOrDefault();

上面的代码真的是你的循环,只是形式更漂亮。它做同样的事情,它接受前一个任务(在使用虚拟“noop”Task 启动之后),然后以ContinueWith 的形式添加一个延续(将延续分配给进程中的当前任务)循环的下一次迭代,在调用LastOrDefault 时执行)。

【讨论】:

    【解决方案2】:

    你可以使用静态扩展ContinueWhenAllhere

    所以你可以传递多个任务。


    更新

    您可以使用这样的链接扩展:

    public static class MyTaskExtensions
    {
        public static Task BuildChain(this Task task, 
            IEnumerable<Action<Task>> actions)
        {
            if (!actions.Any())
                return task;
            else
            {
                Task continueWith = task.ContinueWith(actions.First());
                return continueWith.BuildChain(actions.Skip(1));
            }
        }
    }
    

    【讨论】:

    • @Aliostad:我不认为这是答案,因为它们都依赖于前一个完成(t3 依赖于 t2,t2 依赖于 t1,等等)。
    • 是的,但我想你可以分批完成任务,所以每一个都分批完成。
    • @Aliostad:这没有意义;对 OP 定义的每个先前任务都有明显的依赖关系,等待所有任务然后继续将产生完全不同的效果。
    • @Aliostad:我已格式化您的代码以提高可读性,但我还将if (actions.Count() == 0) 更改为if (!actions.Any()),因为Count() == 0(或Count() != 0))是@987654322 @
    • @Aliostad:上面的代码还有另一个问题。您为每个递归迭代传递actions.Skip(1)。这会导致每次从头开始计算枚举,导致操作数等于N 的总和(即N + (N - 1) + (N - 2) + ... + 1。对于较大的N,这可能会对性能产生很大影响(更不用说由于递归而生成的堆栈)。我强烈建议您重新访问该方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多