MVVM – Lambda vs INotifyPropertyChanged vs DependencyObject

January 26th, 2010 Software Design, WPF

It has been about 1.5 years since I last posted. When the market crashed I became fascinated by world of trading (and software) and applied a bit of WPF knowledge to some research and software for another blog. I have 20+ topics still pending for this blog, so there is plenty to write about in 2010 and beyond.

I have been using the MVVM pattern since the beginning of 2008. Since that time there have been plenty of complaints about INotifyPropertyChanged and how developers do not like using strings, etc. Last year several bloggers presented type-safe alternatives that used either reflection or lambda expressions. I really like the elegance and simplicity of the lambda expression, but many are quick to point out the poor performance (same for reflection). Unfortunately ‘poor performance’ says little about usefulness of an implementation. The performance needs to be quantified and compared against all implementations so that ‘poor’ can be put in perspective. Speed is not the only issue, as memory should be compared as well.

This article assumes the reader knows how to use INotifyPropertyChanged and DependencyObjects. (Note: the rest of this article will refer to the string implementation as INotifyPropertyChanged or just INotify). The lambda implementation that is used for the tests is as follows:

INotifyPropertyChanged with Lambda

public static class MvvmExtensions

{

    public static void Raise(this PropertyChangedEventHandler handler, object sender, Expression<Func<object>> expression)

    {

        if (handler != null)

        {

            if (expression.NodeType != ExpressionType.Lambda)

            {

                throw new ArgumentException(“Value must be a lamda expression”, “expression”);

            }

 

            var body = expression.Body as MemberExpression;

 

            if (body == null)

            {

                throw new ArgumentException(“‘x’ should be a member expression”);

            }

 

            string propertyName = body.Member.Name;

            handler(sender, new PropertyChangedEventArgs(propertyName));

        }

    }

}

public class DummyLambdaViewModel : INotifyPropertyChanged

{

    private string _dummyProperty;

 

    public string DummyProperty

    {

        get

        {

            return this._dummyProperty;

        }

        set

        {

            this._dummyProperty = value;

            OnPropertyChanged(() => this.DummyProperty);

        }

    }

 

    protected virtual void OnPropertyChanged(Expression<Func<object>> expression)

    {

        this.PropertyChanged.Raise(this, expression);

    }

 

    public event PropertyChangedEventHandler PropertyChanged;

}

Since many developers like to use a base view model class, if the property changed method is put in the base class then children will easily get the support for the lambda expression:

public abstract class ViewModelBase : INotifyPropertyChanged

{

    public ViewModelBase()

    {

    }

 

    protected virtual void OnPropertyChanged(Expression<Func<object>> expression)

    {

        this.PropertyChanged.Raise(this, expression);

    }

 

    public event PropertyChangedEventHandler PropertyChanged;

}

The derived class is now a bit more clean.

public class DummyLambdaViewModel : ViewModelBase

{

    private string _dummyProperty;

 

    public string DummyProperty

    {

        get

        {

            return this._dummyProperty;

        }

        set

        {

            this._dummyProperty = value;

            OnPropertyChanged(() => this.DummyProperty);

        }

    }

}

References
The lambda expression code was taken from the following blogs
http://www.jphamilton.net/post/MVVM-with-Type-Safe-INotifyPropertyChanged.aspx
http://blog.decarufel.net/2009/07/how-to-use-inotifypropertychanged-type_22.html
http://consultingblogs.emc.com/merrickchaffer/archive/2010/01/22/a-simple-implementation-of-inotifypropertychanged.aspx

Testing without WPF Bindings
There are essentially two components to lambda property change notification that cost performance. The first is the creation of the expression (such as () => this.DummyProperty). The second is the actual WPF binding infrastructure that affects all of the property change notification implementations. String property change events have virtually no ‘expression creation’ processing time since it is just a hard coded string (such as “DummyProperty”). By raising property change events when no bindings are attached (and thus no listener to the viewmodel’s PropertyChanged event), we can compare the ‘expression creation’ performance costs of the various property change implementations.

The lambda expressions are roughly 20 times slower than both string INotify and DependencyObjects when the WPF binding infrastructure is not included, giving us a measure of the raw performance cost of just raising the property change event. So far the performance cost of lambda expressions is living up to the ‘poor performance’ label.

Testing with WPF Bindings
Since the prior test is only part of the total processing required for property change notification, it is important to test again with a WPF binding in place so that the WPF binding system can work its magic against the property change events. By having a XAML element (such as a TextBlock) bind its Text property to a property of a viewmodel, WPF’s binding system will now be listening for the property change events and doing its own reflection and internal property management.

Once the WPF binding system is included in the performance tests, the lambda expression implementation drops from 20 times slower to only around 3 times slower. Even though using lambda expressions is slower than the alternatives, testing with the WPF binding system shows the performance hit is probably not as big as many have perceived it to be. Using  property change notification on a DependencyObject is the fastest technique since it was designed for that purpose, allowing the WPF binding system to listen to property change events with virtually no overhead and no reflection. However, like the INotify implementation, it uses a string for the property name identification.

Memory Usage
Performance is only half the story. In order to make proper design decisions, it is important to also know the memory characteristics of the various property change techniques. By using a profiler we can measure the number of objects created and destroyed, as well as bytes used during each property change request. The WPF binding system is included in the measurements.

The lambda expressions use almost 7 times the memory as INotify for each property change event, while the DependencyObject property change notification uses no memory at all (but the class itself uses memory). The following screenshot from the profiler shows the WPF binding system objects that are created and destroyed during the INotify event (1,000,000 events):

These are the objects and memory used for the lambda expression (1,000,000 events)

General Guidelines
With this performance and memory usage information we can summarize some loose guidelines for when to use each property change mechanism. Since the DispatcherObject is a WPF class, it has its own set of memory requirements to support

  • DispatcherObject: Use if speed critical and frequent property change events occur
  • INotifyPropertyChanged: Use if large numbers of viewmodels are created (it is more lightweight than DependencyObject), but speed is also important
  • Lambda Expressions: Use for type-safe property change notification when speed is not critical.

Test Application
You can download the application and code used for these tests here. The code is junk code, and is not a demonstration of proper design, testing, or MVVM principles.

Disclaimer
These tests were performed using a viewmodel with only one property. Performance can differ on viewmodels with many properties. Tests were also performed by raising the property change notifications in a loop. Real world performance can vary due to locality of reference.

Shout it

kick it on DotNetKicks.com

Article List

Comments Off
July 22nd, 2008 Uncategorized

2008/07/04 – A Thread-Safe IDisposable Base Class
2008/06/24 – DelegateMarshaler – Replace Control.InvokeRequired and Control.Invoke
2008/06/18 – Simplifying UI and Worker Threads – DelegateMarshaler Revisited
2008/06/17 – Events and Threads
2008/06/10 – Stop Polluting the UI Thread – Use a DelegateMarshaler
2008/05/28 – Bloglist
2008/05/22 – Programmatically Selecting an Item in a TreeView
2008/04/15 – QbDirectoryViz
2008/04/05 – QbColorViz
2008/03/30 – Simple WPF Progress Window with Cancelation
2008/02/10 – Subtle Multithreading Bugs – Part 1
2008/01/20 – WPF Application Design and Architecture
2008/01/06 – WPF Cross-Thread Collection Binding – Part 4 – The Grand Solution
2008/01/05 – WPF Cross-Thread Collection Binding – Part 3 – Working Property Change Events
2008/01/05 – WPF Cross-Thread Collection Binding – Part 2 – Property Change Events
2008/01/01 – WPF Cross-Thread Collection Binding – Part 1

A Thread-Safe IDisposable Base Class

Comments Off
July 22nd, 2008 C#

Davy Brion is in the same situation as me. Every time we need to implement IDisposable (rarely) we have to look up the recommended pattern. Therefore he came up with an abstract base class that provides the proper plumbing and method signatures. All it takes is deriving from this utility class and overriding the DisposeManagedResources() method, and you have your IDisposable class. Obviously deriving from a utility class does not fit every scenario, but it works great for most of my needs.

I liked the idea so much that I decided to take it a bit further and make it ‘Thread-Safe’. In other words, any thread can call Dispose() on an object that derives from the following ManagedDisposable class, and the dispose plumbing will only execute once. The class is not actually thread-safe

The ManagedDisposable Implementation:

public abstract class ManagedDisposable : IDisposable

{

private int _disposed;

 

protected ManagedDisposable()

{

this._disposed = 0;

}

 

public bool IsDisposed

{

get

{

return this._disposed == 1;

}

}

 

public void Dispose()

{

Dispose(true);

GC.SuppressFinalize(this);

}

 

protected virtual void Dispose(bool disposing)

{

if (Interlocked.CompareExchange(ref this._disposed, 1, 0) == 0)

{

if (disposing)

{

DisposeManagedResources();

}

 

DisposeUnmanagedResources();

}

}

 

/// <summary>

/// Helper method so subclasses can easily throw if disposed

/// </summary>

protected void ThrowIfDisposed()

{

if (this.IsDisposed == true)

{

throw new ObjectDisposedException(this.GetType().FullName);

}

}

 

protected virtual void DisposeManagedResources()

{

}

 

protected virtual void DisposeUnmanagedResources()

{

}

}

Derived Class Example:

 

public class MyThreadingObject : ManagedDisposable

{

private SharedResource _sharedResource;

 

public MyThreadingObject()

{

}

 

public void Start()

{

Thread thread = new Thread(ThreadMethod);

thread.Start();

}

 

private void ThreadMethod()

{

this._sharedResource = new SharedResource();

 

for (int i = 0; i < 10; ++i)

{

SharedResource sharedResource = this._sharedResource;

if (sharedResource != null)

{

lock (sharedResource)

{

//do some work

//sharedResource.Process();

}

}

 

Thread.Sleep(1000); //do some other work

}

}

 

protected override void DisposeManagedResources()

{

SharedResource sharedResource = this._sharedResource;

 

if (sharedResource != null)

{

lock (sharedResource)

{

sharedResource.Dispose();

this._sharedResource = null;

}

}

}

}

Notice how there is another element to making the implementation thread-safe. Derived classes still need to protect access to their shared resource(s) via a lock. In the case above, a lock is acquired each time the SharedResource is accessed. If such a lock did not exist, then a race condition could exist where the DisposeManagedResources() is called from another thread (disposing and setting the _sharedResource to null) while the ThreadMethod() attempts to use the resource.

Some may also have noticed how there is no finalizer method in the ManagedDisposable. This is because there are significant costs associated with finalization. If a finalizer is needed, use this class instead:

UnManagedDisposable Implementation

public abstract class UnManagedDisposable : ManagedDisposable

{

// Use C# destructor syntax for finalization code.

// This destructor will run only if the Dispose method

// does not get called.

// It gives your base class the opportunity to finalize.

// Do not provide destructors in types derived from this class.

~UnManagedDisposable()

{

Dispose(false);

}

}

Ultimately if you are using unmanaged resources you can still use the first implementation, it just means the developer is completely responsible for calling the Dispose() method to release both managed and unmanaged resources. Otherwise the unmanaged resources will be leaked. If the second class is used, then even if a developer does not call Dispose() the destructor will eventually be called [Dispose(false) which will call DisposeUnmanagedResources()] by the garbage collector. A quick performance test indicated that ManagedDisposable is 5 times faster than UnManagedDisposable (when Dispose is not called).

An example of something that would ideally implement the UnManagedDisposable is the .NET Font class. If you use fonts and do not call Dispose(), the garbage collector will clean up after you eventually and free the unmanaged font resources. Really fonts should be disposed once they are no longer in use to immediately free these unmanaged resources, but the truth is thousands of developers and components do not always follow this suggestion.

If you don’t like two classes, just copy thr destructor code into the ManagedDisposable (and perhaps give it a better name).

Resources

kick it on DotNetKicks.com

DelegateMarshaler – Replace Control.InvokeRequired and Control.Invoke

Comments Off
July 22nd, 2008 Multithreading

This is the third visitation of the topic of UI and worker thread interaction. Based upon excellent feedback through the comments (thanks Peter Ritchie and others) I have renamed and modified the previous ThreadBarrier implementation (which was a poor name to begin with since a thread barrier concept already represents something else). The previous pattern of encapsulating a thread and communicating to the UI via events raised on the UI thread is still my recommendation: see the first post for a long winded explanation, and the second post for more examples. However, there are many people that already have existing code that uses the Control.InvokeRequired and Control.Invoke pattern such as:

delegate void UpdateProgressDelegate(int progress);

 

public void UpdateProgressBar(int progress)

{

if (this.InvokeRequired == false)

{

this.progressBarDownload.Value = progress;

}

else

{

this.Invoke(new UpdateProgressDelegate(UpdateProgressBar), new object[] { progress });

}

}

The new implementation is intended to replace this code and support the original ThreadBarrier concept.

Introducing the DelegateMarshaler

The DelegateMarshaler implementation is virtually identical to the ThreadBarrier except for four minor differences:

  1. The marshaler is created using a static method DelegateMarshaler.Create() so an exception can be thrown if no SynchronizationContext exists (console app, or before UI is started, etc.)
  2. If the calling thread is already the target thread (UI thread), then the delegate is invoked normally rather than a cross thread invoke. This is similar to InvokeRequired being false.
  3. The DelegateMarshaler supports methods with 0 to 4 arguments.
  4. Static methods wrap ThreadPool.QueueUserWorkItem in a type safe way.

A compact example

void buttonDownload_Click(object sender, EventArgs e)

{

DelegateMarshaler marshaler = DelegateMarshaler.Create();

 

DelegateMarshaler.QueueOnThreadPoolThread(

(fileName) =>

{

//simulate download

for (int i = 0; i < 100; ++i)

{

marshaler.Invoke(UpdateProgressBar, i);

Thread.Sleep(50);

}

marshaler.Invoke(ShowDownloadComplete, fileName);

},

“somefile.txt”);

}

 

private void UpdateProgressBar(int progress)

{

this.progressBarDownload.Value = progress;

}

 

private void ShowDownloadComplete(string fileName)

{

this.labelFileDownload.Text = fileName;

}

Using the DelegateMarshaler consists of creating the marshaler on the UI thread and invoking the methods that update the UI (preferably from the worker thread). Invoke will call the method synchronously, and BeginInvoke will call the method asynchronously allowing the worker to continue running while the UI updates. If your thread is a separate method altogether (which is usually the case), you would want to save the DelegateMarshaler instance as a private field in your form or control so it can be used in the thread method.

The DelegateMarshaler Implementation

public sealed class DelegateMarshaler

{

private SynchronizationContext _synchronizationContext;

 

public static DelegateMarshaler Create()

{

if (SynchronizationContext.Current == null)

{

throw new InvalidOperationException(“No SynchronizationContext exists for the current thread.”);

}

return new DelegateMarshaler(SynchronizationContext.Current);

}

 

private DelegateMarshaler(SynchronizationContext synchronizationContext)

{

this._synchronizationContext = synchronizationContext;

}

 

private bool IsMarshalRequired

{

get

{

return this._synchronizationContext != SynchronizationContext.Current;

}

}

 

public void Invoke<T>(Action<T> action, T arg)

{

if (this.IsMarshalRequired == false)

{

// already on the target thread, just invoke delegate directly

action(arg);

}

else

{

// marshal the delegate call to the target thread

this._synchronizationContext.Send(delegate { action(arg); }, null);

}

}

 

//simplifies use of threadpool so arguments do not need to be cast

public static void QueueOnThreadPoolThread<T>(Action<T> action, T arg)

{

ThreadPool.QueueUserWorkItem(delegate { action(arg); });

}

}

It is such a small class, feel free to modify it to fit your needs. Download the sample for the complete code and comments:

DelegateMarshalerSample

Notable Links
http://thevalerios.net/matt/2008/05/a-type-safe-backgroundworker-wrapper/
http://weblogs.asp.net/justin_rogers/articles/126345.aspx
http://www.codeproject.com/KB/cs/AOPInvokeRequired.aspx

kick it on DotNetKicks.com