indexoutofrangeexception в Datatable с Parallel.Foreach

Я пытаюсь увеличить DataTable с IP-адресами в одном столбце с их обратным сопоставлением DNS. Я получаю этот DataTable откуда-то еще. Затем я экспортирую эту таблицу в SQL Server, используя SQLBulkcopy.

Я добавляю два столбца, один для имени DNS и один только для части домена верхнего уровня. Поскольку у меня много IP-адресов и выполнение обратного DNS занимает некоторое время, я использую Parallel для каждого. Как ни странно, я получаю странные непредсказуемые исключения IndexOutOfRangeException в NestedException для параллельного цикла (или иногда вне параллельного цикла, когда я вызываю очистку в таблице данных). Почему?

Вот что я делаю

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

person cloudraven    schedule 03.06.2014    source источник
comment
похоже, вы не добавили ни одной строки в свой datatable   -  person Doan Cuong    schedule 03.06.2014
comment
Я получаю dt из другой части программы, которая загружает данные из текстового файла. я добавлю это   -  person cloudraven    schedule 03.06.2014


Ответы (1)


Поскольку DataTable не является потокобезопасным для многопоточной операции записи.

MSDN говорит:

Этот тип безопасен для многопоточных операций чтения. Вы должны синхронизировать любые операции записи.

Вы пишете новые столбцы с несколькими потоками одновременно, когда в своем Parallel.ForEach вы делаете:

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

Вам необходимо синхронизировать любой вызов записи с вашим DataTable (используя блокировку или какой-либо вид монитора)

person quantdev    schedule 03.06.2014
comment
Да. Это полностью все исправило. Спасибо! - person cloudraven; 03.06.2014