并行任务执行顺序

Cloud9999冲突

我有以下代码:

public IEnumerable<Task> ExecuteJobs(Action[] pJobsToExecute)
{
    var tasks = new Task[pJobsToExecute.Length];
    for (int i = 0; i < pJobsToExecute.Length; i++)
    {
        //tasks[i] = new Task((index) => ProcessJob(pJobsToExecute[(int)index], (int)index), i);
        //tasks[i].Start();
        tasks[i] = new Task(() => ProcessJob(pJobsToExecute[i], i));
        tasks[i].Start();
    }

    return tasks;
}

public void ProcessJob(Action jobToProcess, int index)
{
    // ...
}

我需要记录发送到ProcessJob方法的任务的顺序,为此我使用了index参数。但是这段代码:

tasks[i] = new Task(() => ProcessJob(jobs[i], i));
tasks[i].Start();

不会给出执行动作的正确顺序。此代码将给出正确的顺序:

tasks[i] = new Task((index) => ProcessJob(pJobsToExecute[(int)index], (int)index), i);
tasks[i].Start();

我不明白为什么Task的这种重载可以解决此问题。是否根据实际执行顺序将i传递给index参数?还是我的测试不正确,此代码还会失败吗?

乔恩

问题是您要在循环变量上创建闭包,并在循环i进行后稍后再使用其值。

使用() => ProcessJob(jobs[i], i)编译器创建lambda函数时,将创建对变量的隐藏引用,该变量ifor循环更新ProcessJob作为正在执行的任务的一部分被调用时,将读取相同的引用

您看到的行为是竞争条件的结果:即使您正在循环启动任务,这些任务也会在单独的线程上运行,并且这些线程不会立即开始执行。当它们确实开始时,其值i已被修改(因为循环的更多迭代已完成),并且读取的值ProcessJob是“错误的”。

与版本index变量创建一个本地副本i是从它逻辑上分离的,并且不与改性在一起i; 因此,在任务有机会开始之前,此副本不受更改的影响。您将获得与以下相同(正确)的行为:

var index = i;
// Note that tasks[index] can also be tasks[i] -- it makes no difference
// because that value is used strictly during the current loop iteration
tasks[index] = new Task(() => ProcessJob(pJobsToExecute[index], index));
tasks[index].Start();

如上所述创建捕获的变量的本地副本是解决所有此类问题的解决方案。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

并行执行任务“ n”次

来自分类Dev

并行运行多个执行任务

来自分类Dev

与WhenAll并行执行任务时的任务缓存

来自分类Dev

如何并行而不是顺序执行多个模型?

来自分类Dev

何时并行执行任务是过大的?

来自分类Dev

关于gradle中的任务执行顺序

来自分类Dev

并行执行任务

来自分类Dev

Gradle任务是并行执行的吗?

来自分类Dev

Gulp文件任务执行顺序

来自分类Dev

Celery中的顺序任务执行

来自分类Dev

在并行执行测试时获取顺序日志

来自分类Dev

即使代码“繁重”,并行执行也比顺序执行慢

来自分类Dev

任务执行顺序

来自分类Dev

通过使用JavaFX中的任务数组列表来执行并等待多个并行和顺序任务

来自分类Dev

控制parallel.foreach任务的执行顺序

来自分类Dev

模型的正向定义是在PyTorch中顺序执行还是并行执行?

来自分类Dev

贪婪的顺序/并行任务调度

来自分类Dev

气流DAG中的错误:>>:“列表”和“列表”不支持的操作数类型。任务的顺序和并行执行

来自分类Dev

气流-任务内的并行执行

来自分类Dev

执行顺序阻止任务的并行组

来自分类Dev

并行执行多对并发任务

来自分类Dev

固定顺序并行执行

来自分类Dev

Java中的动态调度并行任务执行

来自分类Dev

顺序执行的纯计算任务

来自分类Dev

如何并行而不是顺序执行多个查询?

来自分类Dev

何时并行执行任务是过大的?

来自分类Dev

映射器顺序执行而不是并行执行

来自分类Dev

并行执行一对任务

来自分类Dev

Luigi任务方法的执行顺序