2017-02-12 4 views
3

Эти два образца одинаковы? Можно ли заменить старый стиль на Invoke и null?Потоковая безопасность сбора событий с нулевым распространением

OLD:

public event EventHandler<MyEventArgs> MyEvent; 
    protected virtual void OnMyEvent(MyEventArgs args) 
    { 
     EventHandler<MyEventArgs> handler = this.MyEvent; 
     if (handler != null) 
      handler(this, args); 
    } 

NEW:

public event EventHandler<MyEventArgs> MyEvent; 
    protected virtual void OnMyEvent(MyEventArgs args) 
    { 
     this.MyEvent?.Invoke(this, args); 
    } 

Null проверка важна, но это понятно. Что такое дополнительная переменная?
Как работает нуль-propogation внутри? Это поточно-безопасный с событиями?

P.S. Что касается безопасности потока в событиях вы можете прочитать здесь:
C# Events and Thread Safety

+0

См. Также: https://codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-invocation-with-c-6/ – VMAtm

+0

Также ссылки по-русски: https://habrahabr.ru/ post/89529/и https://habrahabr.ru/post/240385/ – VMAtm

+0

Это не дубликат .. по крайней мере, проблема потоковой безопасности - это конкретная тема в этом вопросе .. и в предыдущем сообщении ответ говорит о чем-то странном "компилятор генерирует код для оценивать PropertyChanged только один раз, сохраняя результат во временной переменной ".. Он ничего не делает для обеспечения безопасности потоков. Только факт копирования - это вопрос! И это было исследовано на @eocron. Так что это имеет значение. Чтобы понять, что именно происходит, гораздо лучше получить ответ с этого поста, чем предыдущий. – Maxim

ответ

6

Учитывая этот код:

static void Main(string[] args) 
    { 
     var a = new Random(1).Next() > 0 ? new object() : null; 
     var b = a?.GetHashCode(); 
     Console.WriteLine(b); 
    } 

Это то, что я вижу в представлении IL на линии, где монадическая оператор называется в режиме выпуска (VS 2015) :

IL_0016: dup   
IL_0017: brtrue.s  IL_0025 

... //nothing iteresting, just setting null to 'a' and skip IL_0025 area 

IL_0025: callvirt  instance int32 [mscorlib]System.Object::GetHashCode() 

Поясню:

  • DUP - это команда, которая копирует текущее значение на стеке в новый помещенном в этом стеке (в данном случае это просто дублирующее значение «а»)
  • brtrue.s - передает управление для решения, если значение на стек верно/NotNull/ненулевой (как сейчас значение копия «а» - это потокобезопасный использовать его)

Таким образом, ответ на ваш вопрос: ДА, то поток -safe использовать монодичный оператор, потому что он работает над копией.

+0

Спасибо за IL! Довольно ясно сейчас ... это будет копия. – Maxim

+0

Эта версия не сломается, но теоретически она не является поточно-безопасным решением. На практике это решение на уровне ОК – VMAtm

+0

Поднятие самого события является потокобезопасным ... безопасность потоков любого другого кода не имеет отношения. – Maxim

Смежные вопросы