Лучший, потокобезопасный способ доступа к полю один раз, т.е. для удаления

В основном я хочу убедиться, что поле в классе (в данном случае _changedPoller) удалено как можно раньше, когда оно больше не нужно. Я вызываю StopChangedPolling в методе Dispose класса и при возникновении определенных событий. Каков наилучший, потокобезопасный способ удаления поля только один раз? Подходит ли следующий код?

private void StopChangedPolling()
{
    IDisposable changedPoller = Interlocked.CompareExchange(ref _changedPoller, null, _changedPoller);
    if (changedPoller != null)
        changedPoller.Dispose();
}

Во второй раз, когда это вызывается, _changedPoller имеет значение null, и исключение не генерируется, даже несмотря на то, что в документации указано, что ArgumentNullException создается, если адрес location1 является нулевым указателем.


person atlemann    schedule 18.06.2015    source источник
comment
В этом случае вы можете использовать Interlocked.Exchange вместо CompareExchange.   -  person Kevin Gosse    schedule 18.06.2015


Ответы (1)


Вы не передаете нулевой указатель, вы передаете ссылку на нулевую ссылку. Я не думаю, что вы можете спровоцировать исключение

Адрес location1 является нулевым указателем.

в C#, потому что вы не можете создать нулевой управляемый указатель в C#.

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

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

Вы также можете использовать Interlocked.Exchange.

На самом деле есть одна проблема: вы _changedPoller читаете несинхронизированно. Я не уверен, какие гарантии дают ECMA и .NET CLR. Я бы прочитал спецификацию. volatile исправит это. Interlocked.Exchange тоже исправит это, если нет других подобных применений чтения.

person usr    schedule 18.06.2015
comment
You are reading _changedPoller in an unsynchronized way Разве метод Interlocked не должен использовать барьер памяти? - person Kevin Gosse; 18.06.2015
comment
Да, но один из аргументов просто _changedPoller. Это нормальное чтение. - person usr; 18.06.2015
comment
О, хороший улов. Даже с volatile здесь есть условия для гонок. Interlocked.Exchange определенно следует использовать вместо него - person Kevin Gosse; 18.06.2015
comment
Этот материал очень твердый и хрупкий. Я сначала упустил это из виду. Моя рекомендация использовать замок теперь кажется еще более разумной. - person usr; 18.06.2015