незащищенный доступ к члену в собственности get - PullRequest
1 голос
/ 01 июня 2010

У меня есть собственность

    public ObservableCollection<string> Name
    {
        get
        {
            return _nameCache;
        }
    }

_nameCache обновляется несколькими потоками в других методах класса. Обновления защищены замком. Вопрос в том, должен ли я использовать такую ​​же блокировку для моего оператора return? Не приведет ли использование блокировки к состоянию гонки?

Ответы [ 3 ]

1 голос
/ 01 июня 2010

Зависит от того, что вы подразумеваете под обновлено .

Если вы имеете в виду, что ссылка изменена, то есть _nameCache = newvalue;, то, как сказал Марк, да, вы должны (с той же блокировкой) и, нет, вы не получите условия гонки.

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

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

Если это не подходит (потому что вы всегда получаете элементы через индексатор или что-то еще), то вы всегда можете вернуть копию ObservableCollection через это свойство - т.е. return new ObservableCollection<string>(_nameCache);. Это сделает возвращаемое значение свойства недолговечным, но оставит любого вызывающего абонента свободным для перечисления и индексации, не опасаясь искажения состояния в других потоках.

1 голос
/ 01 июня 2010

Да, вы должны. Если вы не добавите блокировку, новейшее значение _nameCache может быть не возвращено.

public ObservableCollection<string> Name
{
    get
    {
        lock (_yourLockObject)
        {
            return _nameCache;
        }
    }
}
0 голосов
/ 01 июня 2010

Да, вы можете использовать один и тот же объект блокировки.Я предполагаю, что у вас объявлена ​​переменная, например, следующая для блокировки: private object _lock = new object(); Если это так, вы можете использовать объект _lock, как в следующем блоке кода.

public ObservableCollection<string> Name 
{ 
    get 
    { 
       lock(_lock)
       {
          return _nameCache; 
       }
    } 
} 

Если вы не реализовали блокировкув ситуации, когда несколько потоков пытаются получить доступ к _nameCache, вы можете получить значение, которое не входило в контекст текущего вызова этого свойства.Так что да, обязательно применять синхронизацию (блокировку), если несколько потоков обращаются к одному и тому же члену класса, такому как свойства, которые вы описали выше.

Наслаждайтесь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...