Проблема блокировки / параллелизма - PullRequest
3 голосов
/ 02 декабря 2011

У меня есть следующий код C #:

1.    List<BandEdge> bandEdgeList;
2.    
3.    bandEdgeList = CicApplication.BandEdgeCache.Where(row => row.Coater == coater).ToList();
4.    foreach (BandEdge bandEdge in bandEdgeList)
5.       {
6.          ...
7.          ...
8.       }

Мой вопрос такой. Как только bandEdgeList заполняется в строке 3, если другой поток изменяет содержимое CicApplication.BandEdgeCache, будет ли содержимое bandEdgeList признано недействительным? У меня есть блокировка в CicApplication.BandEdgeCache getter / setter. Но мне интересно, должен ли я установить блокировку вокруг этого блока кода, чтобы содержимое CicApplication.BandEdgeCache не менялось, пока я работаю с 'bandEdgeList'.

Ответы [ 3 ]

5 голосов
/ 02 декабря 2011

Не автоматически, но это все еще не потокобезопасно.Он может выдать InvalidOperationException.

. После вызова ToList он сохраняет копию этих ссылок.Но если другой поток изменяет BandEdgeCache, пока это происходит, происходят плохие вещи.

Итак, вы должны заблокировать все ссылки на BandEdgeCache.

Но в соответствии с сохраненным списком, это было бы безопасно, но изменение любого BandEdge не является поточно-ориентированнымбез блокировки.

3 голосов
/ 02 декабря 2011

bandEdgeList будет независимой копией (поскольку вы используете ToList()), поэтому вам не нужно блокировать.

Однако, как прокомментировал @Daniel A. White, вам нужно заблокироватьвокруг оператора LINQ, который создает эту копию.

1 голос
/ 02 декабря 2011

Установка блокировки в получателе CicApplication.BandEdgeCache не поможет вам, если он возвращает ссылку на коллекцию.

CicApplication.BandEdgeCache{
  get{lock(_myCollection){return _myCollection;}}
}

возвращает ссылку, но имеет EXITED блокировку, как только она возвращается, поэтому использование функции Where () для ссылки на коллекцию, возвращаемую получателем, выполняется за пределами блокировки и не является потокобезопасным. Другой поток может с радостью изменить коллекцию, в то время как итерация Where выполняется, поскольку блокировка не удерживается - Даниэль прав, InvalidOperationException будет выдан, если другой поток изменяет коллекцию во время создания списка.

После создания списка можно изменить исходную коллекцию без ущерба для доступа к новому списку.

...