不同的任务方法的工作方式不同[重复]

Posted

技术标签:

【中文标题】不同的任务方法的工作方式不同[重复]【英文标题】:Different Task approaches work differently [duplicate] 【发布时间】:2021-08-16 09:45:45 【问题描述】:

我想问一下为什么这两种方法不同,并返回两组不同的值:

在我看来正确的第一个返回值从 0 到 8 并且适用于不同的线程(LINQPad 代码):

void Main()

    var newTasks = Enumerable.Range(0, 9).Select(x => Task.Run(() => DoSomething(x)));

    Task.WhenAll(newTasks);
    

public int DoSomething(int value)

    return value;

其次,我认为这是不正确的,它返回随机值特别是 9,但也适用于不同的线程。

void Main()

    var tasks = new List<Task<int>>();
    
    for (var index = 0; index < 9; index++)
    
        var task = Task.Run(() => DoSomething(index));
        
        tasks.Add(task);
    
    
    Task.WaitAll(tasks.ToArray());
    

public int DoSomething(int value)

    return value;

是否可以修改第二个并获得类似于第一个示例的结果?

感谢您的回答。

【问题讨论】:

相关:Captured variable in a loop in C# 【参考方案1】:

是否可以修改第二个并获得类似于第一个示例的结果?

当您将变量或对象传递给Task.Run(()=&gt; DoSomething(index)) 时,您捕获一个变量。

从某种意义上说,您不仅仅是将该变量作为值或对象发送,而是让该线程直接访问原始变量。 (这是高度概括的,并且有很多细微差别)。

您最有可能遇到的问题是 CLR 正在尝试捕获 index,这是一个 迭代器,其范围不能离开其边界,除非任何尝试这样做都会保留在堆栈中(基本上相同的线程,再次概括)。

当 CLR '捕获'index 时,它只会捕获 index 曾经的随机值(由于竞争条件) - 或 index 曾经的 last 值,即double 不直观,因为您明确告诉它 index 永远不应在此行中到达 9 for (var index = 0; index &lt; 9; index++)

这是一个棘手的问题,当 CLR 捕获 index 时,它会捕获 index 的最后一个值。但是在循环结束后,index 再增加一次,导致9 成为index 的最后一个值。

这可能会导致一大堆问题,尤其是在您使用数组时,我们来IndexOutOfBoundsException

如何解决 修复其实超级简单!只需在循环中创建一个临时变量,然后直接传递它而不是 index

这是一个例子:

void Main()

    var tasks = new List<Task<int>>();
    
    for (var index = 0; index < 9; index++)
    
        int tmpIndex = index;

        var task = Task.Run(() => DoSomething(tmpIndex ));
        
        tasks.Add(task);
    
    
    Task.WaitAll(tasks.ToArray());

是否可以修改第二个并获得类似于第一个示例的结果?

旁注永远不要依赖任务中的数据按顺序排列,除非您明确实施了保证项目按顺序返回的保证TaskScheduler 选择 Tasks 以在 FIFO 中正常运行(先进先出),但是,如果 TaskScheduler 优化、优先排序或转移任务(经常这样做)你的任务将按顺序完成,随后您获得的结果也将不按顺序完成。

【讨论】:

以上是关于不同的任务方法的工作方式不同[重复]的主要内容,如果未能解决你的问题,请参考以下文章

让你与众不同的不是努力,而是思维方式

main 方法在枚举和类中的工作方式是不是不同?

团队任务管理软件哪个好

C++中的奇淫技巧,三种函数调用方法,让小白彻底理解其工作原理

virtualenv 安装使用

文本对齐在两个相同的 div 上的工作方式不同?