【问题标题】:Task.Factory.StartNew() generating object not initialzed errorTask.Factory.StartNew() 生成对象未初始化错误
【发布时间】:2016-03-12 17:27:45
【问题描述】:

我有这个简单的功能,作为一项任务工作,只打印数据集的值。我从主函数和索引传递数据集。问题是我只填充了 2 个数据集索引,但是该函数总是向前跳一个,即在最后一次迭代中,它希望开始读取索引 2,该索引未初始化,因此是异常。

for (int i = 0; i < 2; i++)
{
   tasks.Add(Task.Factory.StartNew(() => {
       int a = i;                     
       showNodeID(dataSet,a);
       }));
}

函数是

private static void showNodeID(DataSet[] ds, int a)
{
    Console.WriteLine(a.ToString());
    Console.WriteLine(ds[a].GetXml());
}   //END

在最后一次迭代中,当我打印 1 但在函数中,如果我打印 a,它将是 2。

【问题讨论】:

    标签: c# .net multithreading task-parallel-library


    【解决方案1】:

    我假设您知道在 lambda 闭包中捕获计数器变量的危险,因为您试图通过将计数器分配给局部范围的变量来避免该问题。但是,您的分配发生得太晚了——当任务开始并复制值时,计数器可能已经在下一次迭代时增加了。要正确避免该问题,您需要在任务之前复制值,而不是在其中:

    for (int i = 0; i < 2; i++)
    {
        int a = i;                     
        tasks.Add(Task.Factory.StartNew(() => 
        {
            showNodeID(dataSet, a);
        }));
    }
    

    如果你只需要执行一个并行循环,你也可以使用:

    Parallel.For(0, 2, i => showNodeID(dataSet, i));
    

    【讨论】:

    • 像魅力一样工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2018-07-10
    • 1970-01-01
    相关资源
    最近更新 更多