2012-06-20 2 views
1

Я получаю следующее исключение, когда я звоню datatable.Copy(), и я не уверен, почему. Я применил блокировку, чтобы избежать этой проблемы, но она, похоже, не исправила ее. Исключение не происходит последовательно, поэтому я знаю, что это связано с потоковой обработкой. Я не понимаю, как работают замки?Коллекция была изменена исключение из datatable.Copy()

System.InvalidOperationException: коллекция была изменена; операция перечисления может не выполняться. на System.Data.RBTree`1.RBTreeEnumerator.MoveNext() в System.Data.DataTable.Copy()

Код:

DataTable dt; 

lock (ClassName.datatable) 
{ 
    dt = ClassName.datatable.Copy(); 
} 

ClassName представляет собой тип, а не объект (была некоторая путаница в моем предыдущем вопросе).

+2

Вы используете один и тот же замок * везде * используйте модификацию или прочитайте таблицу? –

+0

Нет, я не думаю, что знаю. Блокирует ли блокировка() только блокировки блокировки()? Если так, то это, скорее всего, моя ошибка. – BlargleMonster

+2

Да, да. (Ну, или звонки на «Monitor.Enter» для одного и того же монитора.) Очень важно четко понять, что делает «lock», прежде чем двигаться дальше. Вы хотите, чтобы я добавил это (с более подробной информацией) в качестве ответа? –

ответ

3

Судя по комментариям, вы неправильно поняли, как работает lock. Это схема подключения , при которой два потока не могут удерживать блокировку на одном мониторе за раз. Если нить пытается «ввести» блокировку, либо используя оператор lock, либо Monitor.Enter (и связанные с ним вызовы), тот факт, что другой поток содержит, блокировка не имеет значения.

Это немного похоже на наличие ванной комнаты без замка, но «занятый» или «пустой» знак ... no-one принудительно либо изменить сам знак, либо принять любое уведомление о его текущем состоянии .. но если все согласны с, чтобы обойтись, вы избегаете смущающих ситуаций.

Лично я стараюсь избегать блокировки на мониторе, который виден любой другой код, так что я бы, вероятно, иметь:

private readonly object tableLock = new objet(); 
private readonly DataTable table; 

... 

lock (tableLock) 
{ 
    ... 
} 

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

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