indexoutofrangeexception в Datatable с Parallel.Foreach
Я пытаюсь дополнить DataTable с IP-адресами в одном столбце с их обратным отображением DNS. Я получаю этот DataTable откуда-то еще. Затем я экспортирую эту таблицу в SQL Server, используя SQLBulkcopy
Я добавляю два столбца, один для имени DNS и один только для части домена верхнего уровня. Так как у меня много IP-адресов, и обратный DNS занимает некоторое время, я использую Parallel для каждого. Странно, но я получаю странные непредсказуемые исключения IndexOutOfRangeException в NestedException для параллельного цикла (или иногда вне параллельного цикла, когда я вызываю clear в datatable). Зачем?
Вот что я делаю
//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 ответ
Так как DataTable
не является потокобезопасным для многопоточной операции записи.
Этот тип безопасен для многопоточных операций чтения. Вы должны синхронизировать любые операции записи.
Вы пишете новые столбцы с несколькими потоками одновременно, когда в Parallel.ForEach
, ты сделаешь:
row["URL"] = URL;
row["Domain"] = GetTopLevelDomain(URL);
Вам нужно синхронизировать любой письменный вызов с вашим DataTable
(используя замок или какой-либо вид монитора)