2

Everyone has seen the basic example:

private void RaisePropertyChanged(string propertyName)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

But, as a beginner in WPF and MVVM, I haven't been able to find a practical example where the PropertyChanged event:
1. is null
2. is changed by another thread.

Can someone give me a practical example where both happen?

Igor Popov
  • 9,795
  • 7
  • 55
  • 68
  • possible duplicate of [MVVM INotifyPropertyChanged - Thread issues?](http://stackoverflow.com/questions/22268410/mvvm-inotifypropertychanged-thread-issues) – Rohit Vats Mar 08 '14 at 12:08
  • It is related, but it's not the same question! – Igor Popov Mar 08 '14 at 12:09
  • Edit in first question asking for same what you have asked here. – Rohit Vats Mar 08 '14 at 12:11
  • did that... no one bothered answering back... which is understandable: this is another question and it is different than the original... – Igor Popov Mar 08 '14 at 12:14
  • Anyways `PropertyChanged` event is like any other event. What you have been asking is not related to WPF or MVVM pattern. It's behaviour that's valid for any events for which you can find answers [here](http://stackoverflow.com/questions/2582052/event-handlers-not-thread-safe) and [here](http://stackoverflow.com/questions/786383/c-sharp-events-and-thread-safety). – Rohit Vats Mar 08 '14 at 12:18
  • Also refer to the great explanation by Eric Lippert [here](http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx). – Rohit Vats Mar 08 '14 at 12:19
  • @IgorPopov, null case is simple. Create view model, don't bind it to UI and raise event. Multi threaded issue is more difficult to reproduce. I work with multi threaded app and lots of code written before don't use local variable in cases like this and it works so far but it does not mean I want to risk random crashes on 200 kiosks. – dkozl Mar 08 '14 at 12:24
  • @dkozl, but if I use WPF Data Binding? I automatically have an event subscriber and the null check is not necessary anymore. If the null check is not necessary, then also the assignment becomes unnecessary. – Igor Popov Mar 08 '14 at 12:48
  • And what if you don't use binding? How else do you want to check that? And what if you have race condition? If you want to be safe then that's how you raise not only `PropertyChanged` event but every event in multi threaded environment. What I don't understand is what benefit would you get from removing these 2 lines of code and what sort of answer do you expect for this question. – dkozl Mar 08 '14 at 13:01
  • Is there a case where I wouldn't want to use data binding? And I don't care about those 2 lines of code. I just want to **understand why and when** to use those 2 lines. I got the why part, but I don't know **when?** – Igor Popov Mar 08 '14 at 13:06
  • 1
    It's not mandatory for every view model to be visualized when you create/use it. What if you change your mind and don't want to visualize something any more? Your application should account for that. You shouldn't care if or how many views have been created for that view model. Same rule applies to every other event, not only `PropertyChanged` – dkozl Mar 08 '14 at 13:24

1 Answers1

2

A practical example of bullet 1 (null) might be if your run unit tests on your ViewModel. In such a case, there won't be a UI bound to your ViewModel, and if a test method (Test1) updates a property without having subscribed to the PropertyChanged event, you'll get a NullReferenceException.

A (slightly less?) practical example of bullet 2 (threading) might be if a second unit test (Test2) runs at the same time as Test1 above in a different thread. The second test does subscribe to the event some time before Test1 inadvertently triggers the event, but then unsubscribes again right in the middle of the if test:

private void RaisePropertyChanged(string propertyName)
{
    //1: Test1 changes a property, and triggers this event.
    //   Because Test2 earlier subscribed to the event, PropertyChanged is not null here
    if (PropertyChanged != null)
    {
        //2: Test2 sneaks in from a different thread
        //   and *unsubscribes* from PropertyChanged, making it null again.

        //3: Test1 then gets a NullReferenceException here,
        //   because there's no local "handler" variable that kept the original delegate.
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
Sphinxxx
  • 12,484
  • 4
  • 54
  • 84
  • ok... so, testing... what if I don't test GUIs? or avoid using multiple threads for GUIs? I saw it mentioned somewhere... – Igor Popov Mar 10 '14 at 09:15
  • ..and never use your ViewModels for anything but GUI I guess you're safe. After all, this is a better-safe-than-sorry approach. But some day you may want to use one of your ViewModels as a helper class for some other project, and you find yourself in situation 1. Therefore, you should at least check for *null* – Sphinxxx Mar 10 '14 at 13:37
  • Why would I want to use **View** Models for anything else but GUIs? Anyway, I got the idea, I should just put that code in a class like `ObservableObject` and other ViewModels will just extend it... – Igor Popov Mar 10 '14 at 15:45