使用Parallel.Foreach在Datatable中的indexoutofrangeexception

时间:2014-06-03 02:01:34

标签: c# datatable parallel-processing sqlbulkcopy parallel.foreach

我正在尝试使用反向dns映射来扩充一个IP地址在一列中的DataTable。我从其他地方获取此DataTable。然后我使用SQLBulkcopy

将此表导出到SQL Server

我正在添加两列,一列用于dns名称,另一列用于顶级域名部分。我有很多IP并且做反向DNS需要一些时间我每个都使用并行。 奇怪的是,我在NestedException中为并行循环得到了奇怪的不可预测的IndexOutOfRangeExceptions(当我在数据表中调用clear时,有时在并行循环之外)。为什么呢?

这就是我正在做的事情

        //mapping specifies a mapping within the DataTable and the Database

        SqlBulkCopy copy = new SqlBulkCopy(cn);
        foreach (KeyValuePair<int, int> pair in mapping)
        {                                                                       
            copy.ColumnMappings.Add(pair.Key, pair.Value);
        }


        dt.Columns.Add("URL");
        dt.Columns.Add("Domain");
        solver.AddDNSInfo(dt, 1); //second row has the IP
        copy.WriteToServer(dt);
        dt.Clear();     //exceptions are thrown here   




    //ipIndex is the index within the datatable where the IP of interest is. 
    //In my scenario ipIndex=1
    public void AddDNSInfo(DataTable table, int ipIndex)
    {
        Parallel.ForEach(table.AsEnumerable(), row =>
        {
                string URL = GetDNSName((string)row[ipIndex]);
                row["URL"] = URL; //exceptions are thrown here
                row["Domain"] = GetTopLevelDomain(URL);
                Console.Write("*");
        });

1 个答案:

答案 0 :(得分:4)

因为DataTable对于多线程写操作不是线程安全的。

<强> MSDN says:

  

此类型对于多线程读取操作是安全的。您必须同步任何写操作。

当您在Parallel.ForEach执行此操作时,您正在同时编写包含多个主题的新列:

  row["URL"] = URL;
  row["Domain"] = GetTopLevelDomain(URL);

您需要同步对DataTable的任何书写调用(使用锁或某种形式的监视器)