Почему C # не может автоматически обеспечить потокобезопасный доступ к событиям, в отличие от C ++ / CLI? - PullRequest
17 голосов
/ 07 марта 2011

Из документации MSDN для EventHandler Delegate :

В отличие от примеров C # и Visual Basic, пример Visual C ++ код не требует от вас создания потокобезопасная временная переменная. визуальный C ++ версия автоматически обеспечивает потокобезопасный доступ, позволяющий вам поднять событие напрямую.

Почему C # не может автоматически обеспечить потокобезопасный доступ к событиям, где C ++ / CLI может?

Ответы [ 2 ]

3 голосов
/ 07 марта 2011

Этот пост весьма актуален для справочной информации.У события есть три метода доступа: добавить, удалить и поднять.Соответственно добавить обработчик события, удалить его и вызвать событие.Компилятор генерирует его автоматически, когда вы не пишете аксессор явно.

Компилятор C ++ / CLI автоматически генерирует аксессор повышения, если вы его не пишете.Он использует шаблон, который вы видите в коде C # с вспомогательной переменной, которая избегает исключения нулевой ссылки.Так же, как вы видите это в связанном посте.По какой-то таинственной причине язык C # не делает этого.Он даже не позволяет вам определить свой собственный аксессор, вы должны сами поднять событие.Заставляет вас писать код с помощью вспомогательной переменной.

Понятия не имею, почему команда C # приняла это решение.Как правило, команда настоятельно рекомендует избегать автоматически сгенерированного кода, который замедляет выполнение.Принцип C ++ «вы не платите за то, что не используете».Конечно, во многих случаях безопасность потоков не требуется, например, любые события в коде GUI.Это чертовски сложный случай, учитывая низкую стоимость и тот факт, что код GUI в любом случае содержит шаблон.Однако низкоуровневая блокировка в библиотеках C ++ встречается часто.

1 голос
/ 07 марта 2011

Хотя это не совсем дубликат, я думаю, что ответы в на этот вопрос помогут объяснить, почему они не являются поточно-ориентированными с точки зрения реализации.В частности, эти два ответа.

Ответ Марка Гравелла:

ИМО, другие ответы пропускают одну ключевую деталь - что делегаты (ипоэтому события) неизменны.Значение этого заключается в том, что подписка или отмена подписки на обработчик событий не просто добавляет / удаляет список, а скорее заменяет список новым с дополнительным (или на один меньше) элементом.

Поскольку ссылки являются атомарными, это означает, что в момент, который вы делаете:

var handler = SomeEvent;

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

Таким образом, вы проверяете на нулевое значение и вызываете его, и все хорошо.Заметьте, конечно, что все еще есть запутанный сценарий события, возникающего на объекте, который считает, что он отписался пикосекунду назад!

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