C #: вызвать событие из заблокированного блока - PullRequest
2 голосов
/ 19 декабря 2009

Я обычно слышал, что это хорошая идея, чтобы разблокировать любые блокировки перед вызовом слушателей событий, чтобы избежать тупиковых ситуаций. Однако, поскольку блок lock {} повторно входит тем же потоком в C #, нормально ли вызывать события из заблокированного блока или мне нужно сделать копию соответствующих данных состояния и вызвать событие вне блока блокировки?

Если нет, приведите пример, когда было бы трудно вызвать событие из блока lock {}.

Спасибо

Ответы [ 3 ]

9 голосов
/ 19 декабря 2009

Я не помню, чтобы когда-либо возникало необходимость вызывать событие из оператора lock.Но не трудно представить, что дела идут плохо.

Когда вы вызываете событие, вы откладываете выполнение на код, который может быть не вашим.Это особенно верно, если вы пишете какую-то библиотеку или фреймворк, например, который будет использоваться другими.Внутри обработчика событий у вас нет абсолютно никакого контроля над тем, что происходит.Обработчик события может запустить новый поток и дождаться его завершения (т. Е. Join()), прежде чем вернуться.Если этот новый поток вызвал какую-то функцию, заблокированную в той же переменной, что и ваш lock, бинго.Deadlock.

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

4 голосов
/ 19 декабря 2009

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

Смешивание потоков с обработчиками событий, которые вы не контролируете, определенно создает проблемы. В настоящее время у меня возникли некоторые проблемы, потому что я вызвал событие из потока приема последовательного порта. Некоторый код обработчика событий решил заблокировать и дождаться получения другого сообщения от последовательного порта. Это будет долгое ожидание, потому что вы только что заблокировали единственную и только получающую ветку! Я даже не могу злиться на кого-то, потому что я написал оба куска кода (с интервалом в год, так что у меня было время забыть детали).

1 голос
/ 19 декабря 2009

Да, это не будет считаться хорошим дизайном для вызова события из удерживаемой блокировки. Главным образом из-за перехода из заблокированного раздела, и если это вызовет ошибку или возникнет проблема, блокировка не обязательно будет снята.

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

...