C#中线程池中的索引超出范围异常-Task.Run()

Index Out of Range Exception in Thread Pooling in C# -Task.Run()

当我从代码中删除线程池或取消注释 Console.WriteLine() 时,代码可以正常工作,但为了提高性能,我想在单独的任务上处理每个 DataTable 列。它抛出索引超出范围异常。

DataTable dt = new DataTable();
private async void btnExcel_Click(object sender, RoutedEventArgs e)
    {
        dt = new DataTable("worksheet");
        dt.Columns.Add("Id");
        dt.Columns.Add("MobileNo");
        dt.Columns.Add("Name");
        dt.Columns.Add("Name1");
        dt.Columns.Add("Name2");
        dt.Columns.Add("Name3");
        dt.Columns.Add("Name4");

        for (int i = 0; i < 100; i++)
            dt.Rows.Add(i, "99999", "ABC" + i, "n1", "n2", "n3", "n4");

        //var tasksInFlight = new Task[dt.Columns.Count];
        var tasksInFlight = new List<Task>();

        for (int index = 0; index < dt.Columns.Count; index++)
        {
            tasksInFlight.Add(updateDt(index, "col " + index));

        }

        //await Task.Factory.ContinueWhenAll(tasksInFlight, cT => { string a = "abc"; });

        await Task.WhenAll(tasksInFlight);

    }


    public async Task updateDt(int colNum, string data)
    {
        try
        {
            Task t = Task.Run(() =>
            {
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                    // Console.WriteLine("Col Num : " + colNum + "  i = " + i);
                    dt.Rows[i][colNum] = data;
                }
            });

            await t;
        }
        catch (Exception ex)
        {
        }
    }

当你调用tasksInFlight.Add(updateDt(index, "col " + index));时,索引的值没有被读取;您只需存储一个稍后将执行的任务 - 当您调用 Task.WhenAll 时。它是在评估 index 的值时执行任务的时间。这发生在循环结束后 index 的值现在等于 dt.Columns.Count,这超出了数组的范围。

了解 C# 闭包 here

要修复它,您可以这样做:

for (int index = 0; index < dt.Columns.Count; index++)
{
    int tmpIndex = index;
    tasksInFlight.Add(updateDt(tmpIndex, "col " + tmpIndex));
}

编辑:进一步调查后发现 DataTable 不是线程安全的。

除了上述修复之外,还应该在锁中访问 DataTable:

 lock (dt) 
 { 
     dt.Rows[i][colNum] = data; 
 }

但是,除非检索实际数据以放入 DataTable CPU 密集型,否则在这种情况下锁会消除并发的所有好处。