Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Обработка try-catch только верхнего уровня Добавлено: 08.05.12 14:38  

Автор вопроса:  Programmer
Допустим, существует такой код:

  try{
   TestEvent();
  }catch (NullReferenceException) { }


TestEvent может быть равно null. Проверять через if - нельзя.

Существует ли способ обрабатывать только исключение, когда TestEvent = null, но пропускать его, если возникает внутри TestEvent?

Ответить

  Ответы Всего ответов: 10  

Номер ответа: 1
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #1 Добавлено: 08.05.12 14:58
Вопрос стоит настолько нелогично, что возникает вопрос, а зачем, собственно тебе это нужно?

Ответить

Номер ответа: 2
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #2 Добавлено: 08.05.12 15:31
Для многопоточности. После проверки if != null событие может стать null. Если скопировать список делегатов, есть вероятность вызвать отписанное событие. Вызов события из под lock может привести к deadlock-ам.

Ответить

Номер ответа: 3
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #3 Добавлено: 08.05.12 17:25
распространенная проблема. при объявлении евента допиши в конце
  1. = delegate { }

Ответить

Номер ответа: 4
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #4 Добавлено: 08.05.12 21:21
Спасибо, то что надо)

Ответить

Номер ответа: 5
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #5 Добавлено: 13.05.12 11:14
о, на митуй затусили эксперты в области разработки многопоточных приложений

Ответить

Номер ответа: 6
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #6 Добавлено: 13.05.12 11:59
Вот код, код гарантированно (Я ГАРАНТИРУЮ ЭТО) безопасной генерации события. Не упадет если SomeEvent равен null (т.е. на него никто не подписался), если во время проверок кто-то подпишется, отпишется, или произойдет что-то еще.

  1.         public event EventHandler SomeEvent;
  2.  
  3.         public void OnSomeEvent()
  4.         {
  5.             EventHandler handler = (EventHandler)Thread.VolatileRead(ref this.SomeEvent);
  6.             if (handler != null)
  7.             {
  8.                 handler(this, EventArgs.Empty);
  9.             }


AgentFire пишет:
распространенная проблема. при объявлении евента допиши в конце
= delegate { }

говнокод

Programmer пишет:
Если скопировать список делегатов, есть вероятность вызвать отписанное событие.

Типы Delegate, MulticastDelegate (коим, собственно, и является EventHandler) - immutable типы. Это значит что после создания они не могут изменяться.
Если кто-то хочет добавить в цепочку вызовов еще один обработчик (т.е. грубо говоря подписаться на событие), или удалить обрабочтик (отписаться), то создается новый экземпляр типа Delegate, в содержащий модифицированную цепочку обрабочтиков (или null, если из цепочки удалены все обработчики). И этот экземпляр ложится в поле класса, хранящее ссылку на обработчик события.

Аналогично работает тип String. Когда ты модифицируешь строк (например, добавляшеь в конец один символ), создается новый экземпляр строки с добавленным в конец символом. Старый же остается без изменений. С этим как раз связаны потенциальные тормоза если производить много модификаций с обычными String, и поэтому для таких действий рекомендуется использовать muttable StringBuilder.

Копирование ссылки в дотнете - это атомарная операция. Если какой-то другой поток модифицирует ссылку, то копирование будет гарантированно выполнено до или после этой модификации.
Таким образом, если ты скопировал из поля в переменную ссылку на объект, а потом другой поток в это поле положил null, в твоей переменной останется корректная ссылка на старое значение поля. И ты можешь абсолютно безопасно делать проверку на null и вызывать событие.
Использование VolatileRead для чтения значения из поля позволяет избежать проблем, связанных с тем, что на этапе JIT компиляции к коду могут быть применены оптимизации, которые изменят порядок операций (например, проверка ссылки на null будет выполнена до того как она будет скопирована).

Но если учесть что при обращении к обрабочтику события JIT такие оптимизации не использует, то можно писать и так

  1.         public event EventHandler SomeEvent;
  2.  
  3.         public void OnSomeEvent()
  4.         {
  5.             EventHandler handler = this.SomeEvent;
  6.             if (handler != null)
  7.             {
  8.                 handler(this, EventArgs.Empty);
  9.             }


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

=====================================================

Как я понимаю, твое событие объявлено без параметров типа

  1.         public delegate void MyEventDelegate();
  2.  
  3.         public event MyEventDelegate MyEvent;

Если так, это нарушение конвенции сигнатуры событий в .NET. События должны иметь тип EventHandler или EventHandler<T>. 2 параметра, первый - sender, второй - пустой EventArgs, или наследник от EventArgs, содержащий дополнительные параметры.

Ответить

Номер ответа: 7
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #7 Добавлено: 13.05.12 14:04
Спасибо, про immutable типы я не знал. А что плохо в том, чтобы писать как предложил AgentFire? Имхо, его код компактнее и однозначнее в данном случае.

Ответить

Номер ответа: 8
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #8 Добавлено: 13.05.12 14:35
Здесь подробнее расписано
http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx

Ответить

Номер ответа: 9
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #9 Добавлено: 13.05.12 22:56
Имхо, его код компактнее

Компактнее, не значит правильнее.. его совет это, по сути, заглушка чтоб не писать инвокатор... обычная лень..
Кроме того, существую определенные правила при проектировании классов.. и события не являются исключениями. На любое событие, как правило, пишется защищенный виртуальный инвокатор с приставкой On и без параметра sender..

Ответить

Номер ответа: 10
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #10 Добавлено: 13.05.12 23:02
Если ты обращал внимание то в большинстве случаев они идут парами..
MouseMove - событие
OnMouseMove - инвокатор (чаще всего делают как protected virtual)
Этого правила и надо придерживаться...

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам