Parallel.Foreachを使用したDatatableでのインデックスの範囲外の例外

c# datatable parallel.foreach parallel-processing sqlbulkcopy

質問

私は逆のdnsマッピングで1つの列にIPアドレスを持つDataTableを増やそうとしています。このDataTableは別の場所から取得しています。私はSQLBulkcopyを使用してSQL Serverにこのテーブルをエクスポートしています

私は2つの列を追加しています.1つはDNS名用で、もう1つはトップレベルドメイン部分のみです。私はたくさんのIPを持っていて、逆DNSをするのは、それぞれのためにParallelを使っている時間がかかります。不思議なことに、パラレル・ループ(または、データ・テーブル内でクリアをコールするときにパラレル・ループの外にあることもある)のNestedException内で、予期せぬ予測不可能なIndexOutOfRangeExceptionsが発生します。どうして?

私がやっていることがここにあります

        //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("*");
        });

受け入れられた回答

DataTableはマルチスレッド書き込み操作ではスレッドセーフではないためです。

MSDNさんの言葉:

このタイプは、マルチスレッド読取り操作で安全です。すべての書き込み操作を同期する必要があります。

あなたはParallel.ForEachで同時に複数のスレッドを持つ新しい列を作成しています:

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

書き込み呼び出しをDataTableに同期する必要がありDataTable (ロックや何らかの形式のモニタを使用)



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ