Существует так много сбоев, которые могут произойти, если вы склонны обновлять список и читать его в многопоточном коде, например, скажем, у нас есть следующий сценарий:
//c#
List<object> myList...
//at reading thread
if (myList.Count > 0)
{
object item = myList[0];//get the item at the first index of the collection.
}
//at writing thread
myList.Clear();
Поток записи обновляет список в то же время, когда поток чтения читает из списка, поэтому предположим, что выполнение было следующим:
Поток чтения проверяет, есть ли элементы в коллекции, и находит, что на нем есть некоторые элементы ".Count > 0
верно", поэтому он продолжается, но прежде чем он достигнет следующей строки, переключение контекста потока приостанавливает поток чтения, переключаясь на поток записи, поэтому он выполняет свою код myList.Clear();
в этот момент контекст потока переключается обратно на поток чтения, чтобы продолжить его выполнение, поэтому он пытается получить myList[0]
, но коллекция была пустой в этот момент потоком записи, поэтому он завершится ошибкой с исключением IndexOutOfRange
..
Другой сценарий: если поток чтения, в котором выполняется итерация, выбрасывает коллекцию с использованием foreach
, а поток записи просто меняет коллекцию, «добавляет/удаляет» некоторые элементы, он снова выдает исключение из-за изменения коллекции во время цикла.
Таким образом, вы должны использовать некоторый механизм синхронизации при взаимодействии со списком, таким как lock
в C# или с использованием класса Monitor
. Однако, если вы используете 4.0
, вы можете переключиться на использование ConcurrentCollection
вместо обычных списков, они являются потокобезопасными коллекциями.
19.08.2011