2012-02-15 2 views
1

когда используются следующим образомли Parallel.ForEach (DataTable.AsEnumerable() поточно

Parallel.ForEach(DataTable.AsEnumerable(), dr => { 

    string str = dr["field1"].ToString(); 
    //.... other stuff 
    dr["f1"] = o.A; 
    dr["f2"] = o.B; 
    dr["f3"] = o.C; 

}); 

где каждый поток работает по своему собственному DataRow

Я бы предположить, нет, но, но там это высказывание о предположениях. ...

+1

'DataTable' - чрезвычайно сложный зверь. – SLaks

+0

Позвольте мне угадать, когда развертывать приложение на нескольких процессорах. может быть глупым ответом. –

+1

«Предположения делают задницу из' u' и 'mptions'? Psst .. высказывание о «предполагайте» не «предположения»;) – Jamiec

ответ

4

documentation класса DataRow окончательно утверждает, что

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

Не может быть более конкретным, чем это.

В любом случае параллельная запись в Datatable, вероятно, не будет хорошо масштабироваться. Масштабируемость страдает, когда у вас есть несколько потоков, обращающихся к общему состоянию, и единый тип данных является вполне очевидным совместным состоянием. Более того, если вы не работаете с оборудованием NUMA, ваши ядра процессора будут бороться за доступ к одной и той же шине памяти.

Лучшим решением является возвращение любых результатов от параллельной обработки («прочее вещество») в отдельной структуре (например, one of the concurrent collections) и применение изменений от одного потока при завершении цикла.

Другой вариант - использовать PLINQ для вычисления результатов и итерации по ним с помощью простого foreach, чтобы применить изменения к DataTable.

Еще лучшим решением было бы полностью отказаться от исходных данных и вернуть новый объект, который содержит нужные вам поля. Если ваш код не требует, чтобы результат был DataTable, вы могли бы просто вернуть результаты в виде IEnumerable

+0

Если я понимаю ваш ответ: если, например, мне нужно было изменить столбец X в таблице данных, содержащей 200 строк, я мог бы вывести значение из столбца X для всех 200 строк и сохранить его в параллельной коллекции, а затем выполнить параллель .For() в этой параллельной коллекции, чтобы изменить значение, затем цикл в одном потоке для обновления исходного столбца X DataTable из значений в параллельной коллекции? –

+0

Нет, наоборот. Нет проблем с чтением значений из нескольких потоков, поэтому нет необходимости их извлекать. Предполагая, что на самом деле необходимо параллельно обрабатывать 200 значений, вы должны собирать результаты обработки в параллельной коллекции, а затем применять их обратно к таблице из одного потока. –

+0

200 было просто случайным числом, о котором я думал, но его больше, как и многие тысячи. В моей ситуации у меня есть таблица в базе данных, где 1 столбец в этой таблице зашифрован. Я загружаю все строки из этой таблицы в db в DataTable, и затем мне нужно перебирать все строки и расшифровывать этот столбец - настолько простая проблема. Я думаю, что понимаю ваши комментарии в том, что я могу одновременно считывать значения и расшифровывать их, но для обновления исходных строк и столбцов я должен будет сделать это в одном потоке. –

1

Если какой-либо из этих столбцов индексируются, это, безусловно, небезопасно.
Если нет, то может быть безопасным, но я не думаю, что так.

+0

Что вы подразумеваете под «if ... columns indexed»? шаблон доступа, как показано выше, – Kumar

+0

@Kumar: 'DataTable' имеет индексы, как и SQL Server. Изменение индексированного столбца, безусловно, небезопасно даже в строках. – SLaks

+0

столбец defs статичен, поэтому не стоит беспокоиться об этом фронте, подумал, что это так в приложении, построенном с использованием .net 2, предполагая, что perf shd будет еще лучше в .net 4 – Kumar

4

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

+0

в общем случае да, но каждый поток работает с другой строкой, поэтому в строке не существует параллельной операции, поэтому вопросы об этом конкретном сценарии – Kumar

+1

@Kumar Несмотря на то, что каждый поток работает с другой строкой, строка содержащихся в DataTable, и когда у вас есть операции записи в этой строке, влияет состояние DataTable. – sarvesh

+0

Любые детали/указатели на то, что конкретно затронуто? – Kumar

Смежные вопросы