Най-добрият, безопасен начин за еднократен достъп до поле, т.е. за изхвърляне

По принцип искам да се уверя, че поле в клас (в този случай _changedPoller) е Disposed възможно най-рано, когато вече не е необходимо. Извиквам 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)


Вие не предавате нулев указател, вие предавате препратка към нулева препратка. Не мисля, че можеш да провокираш изключението

Адресът на местоположение1 е нулев указател.

в 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