Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

var handler = SomeEvent;

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

Итак, вы проверяете значение null и вызываете его, и все хорошо. Обратите внимание, конечно, что все еще запутанный сценарий события, возникающего на объекте что он отказался от подписки picosecond ago!