Article List

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

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

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

Simplifying UI and Worker Threads - DelegateMarshaler Revisited

July 22nd, 2008 Multithreading

Background

Update - ThreadBarrier was a poorly chosen name, use the latest DelegateMarshaler implementation instead.

Previously I introduced the ThreadBarrier pattern which describes a simple technique for allowing worker threads to easily and safely communicate with controls on the UI thread. The key points from the previous article are:

A worker thread is completely contained within a class (and any objects the class references)

  1. Events from this worker class are raised on the UI thread
  2. A SynchronizationContext is used rather than Control.Invoke or Dispatcher.Invoke
  3. The UI code does not have to worry about what thread is executing, it always assumes the UI thread (keeps code clean)
  4. The ThreadBarrier needs to be created on a UI thread to capture the UI’s SynchronizationContext

Today’s article is a revisitation of the pattern to demonstrate several ways the technique can be used, as well as describe the flaw in the previous implementation. Yesterday’s article on events and threads provides an in depth background on the subtleties of events and multithreading. The contents of today’s post include:

  • The New ThreadBarrier Code
  • Sample UI and Worker Classes
  • ThreadBarrier Technique #1: Subclassing an existing worker thread class
  • ThreadBarrier Technique #2: Using extension methods on a SynchronizationContext
  • ThreadBarrier Technique #3: Deriving from a ThreadBarrier
  • ThreadBarrier Technique #4: Creating an instance of a ThreadBarrier
  • ThreadBarrier Technique #5: Creating an adapter class to propagate events
  • The Original ThreadBarrier Implementation Flaw
  • ThreadBarrier FAQ

Download the examples.

The New ThreadBarrier Code

.NET 2.0

public class ThreadBarrier

{

private SynchronizationContext _synchronizationContext;

 

public ThreadBarrier()

{

this._synchronizationContext = AsyncOperationManager.SynchronizationContext;

}

 

public void Post<T>(Action<T> raiseEventMethod, T e)

where T : EventArgs

{

if (this._synchronizationContext == null)

{

ThreadPool.QueueUserWorkItem(delegate { raiseEventMethod(e); });

}

else

{

this._synchronizationContext.Post(delegate { raiseEventMethod(e); }, null);

}

}

}

.NET 3.5

public static class ThreadBarrierExtensions

{

public static void Post<T>(this SynchronizationContext synchronizationContext, Action<T> raiseEventMethod, T eventArgs)

where T : EventArgs

{

if (synchronizationContext == null)

{

ThreadPool.QueueUserWorkItem((e) => raiseEventMethod((T)e), eventArgs);

}

else

{

synchronizationContext.Post((e) => raiseEventMethod((T)e), eventArgs);

}

}

}

The use of an anonymous delegate can be used for either implementation. The .NET 3.5 version uses a lambda expression just to demonstrate an alternate way of invoking the action.

Sample UI and Worker Classes

The sample UI and worker classes are very simple examples that will be the reference code for the techniques that follow. The UI code remains virtually unchanged throughout every technique which is ideal since it should not be concerned with threading:

These classes do not work together as is, they need a ThreadBarrier.

Sample Worker Class

public class WeatherChecker

{

public event EventHandler<WeatherEventArgs> TemperatureChanged;

public event EventHandler<WeatherEventArgs> HumidityChanged;

public event EventHandler<WeatherEventArgs> WindChanged;

public event EventHandler Stopped;

 

private bool _isStopRequested;

private Random _random;

 

public WeatherChecker()

{

this._isStopRequested = false;

 

//used for generating random weather information

this._random = new Random((int)DateTime.Now.Ticks);

}

 

public void Start()

{

Thread thread = new Thread(new ThreadStart(CheckWeather));

thread.IsBackground = true; //prevents thread from keeping app alive when app is closed

thread.Start();

}

 

private void CheckWeather()

{

while (this._isStopRequested == false)

{

OnTemperatureChanged(new WeatherEventArgs(Rand(30f)));

OnWindChanged(new WeatherEventArgs(Rand(15f)));

OnHumidityChanged(new WeatherEventArgs(Rand(100f)));

 

//Updates roughly 4 times per second

Thread.Sleep(250);

}

 

OnStopped(EventArgs.Empty);

}

 

public void RequestStop()

{

this._isStopRequested = true;

}

 

private float Rand(float max)

{

return (float)this._random.NextDouble() * max;

}

 

protected virtual void OnTemperatureChanged(WeatherEventArgs e)

{

if (this.TemperatureChanged != null)

{

this.TemperatureChanged(this, e);

}

}

protected virtual void OnHumidityChanged(WeatherEventArgs e)

{

if (this.HumidityChanged != null)

{

this.HumidityChanged(this, e);

}

}

protected virtual void OnWindChanged(WeatherEventArgs e)

{

if (this.WindChanged != null)

{

this.WindChanged(this, e);

}

}

protected virtual void OnStopped(EventArgs e)

{

if (this.Stopped != null)

{

this.Stopped(this, e);

}

}

}

Sample UI Class

public partial class Form1 : Form

{

private WeatherChecker _weatherChecker;

 

public Form1()

{

InitializeComponent();

}

 

private void buttonStart_Click(object sender, EventArgs e)

{

this.buttonStart.Enabled = false;

this.buttonStop.Enabled = true;

 

this._weatherChecker = new WeatherChecker();

this._weatherChecker.TemperatureChanged += new EventHandler<WeatherEventArgs>(_weatherChecker_TemperatureChanged);

this._weatherChecker.HumidityChanged += new EventHandler<WeatherEventArgs>(_weatherChecker_HumidityChanged);

this._weatherChecker.WindChanged += new EventHandler<WeatherEventArgs>(_weatherChecker_WindChanged);

this._weatherChecker.Stopped += new EventHandler(_weatherChecker_Stopped);

 

this._weatherChecker.Start();

}

 

private void buttonStop_Click(object sender, EventArgs e)

{

this._weatherChecker.RequestStop();

}

 

void _weatherChecker_TemperatureChanged(object sender, WeatherEventArgs e)

{

this.labelTemperature.Text = String.Format(“{0:F1} C”, e.Value);

}

 

void _weatherChecker_HumidityChanged(object sender, WeatherEventArgs e)

{

this.labelHumidity.Text = String.Format(“{0:F0}%”, e.Value);

}

 

void _weatherChecker_WindChanged(object sender, WeatherEventArgs e)

{

this.labelWind.Text = String.Format(“{0:F0} mph”, e.Value);

}

 

void _weatherChecker_Stopped(object sender, EventArgs e)

{

this.buttonStop.Enabled = false;

this.buttonStart.Enabled = true;

 

this._weatherChecker = null;

}

}

ThreadBarrier Technique #1: Subclassing an existing worker thread class

The two classes above are doing nothing special to communicate with on another. An attempt to use the two together would fail since the worker class is raising events on the worker thread which is not allowed to access controls on the UI thread. Amazingly using a ThreadBarrier in the following way causes all events from the worker class to be automatically raised on the UI thread:

public class ThreadBarrierWeatherChecker : WeatherChecker

{

private ThreadBarrier _threadBarrier;

 

public ThreadBarrierWeatherChecker()

{

this._threadBarrier = new ThreadBarrier();

}

 

protected override void OnTemperatureChanged(WeatherEventArgs e)

{

this._threadBarrier.Post(base.OnTemperatureChanged, e);

}

 

protected override void OnWindChanged(WeatherEventArgs e)

{

this._threadBarrier.Post(base.OnWindChanged, e);

}

 

protected override void OnHumidityChanged(WeatherEventArgs e)

{

this._threadBarrier.Post(base.OnHumidityChanged, e);

}

 

protected override void OnStopped(EventArgs e)

{

this._threadBarrier.Post(base.OnStopped, e);

}

}

That’s it! All it took was deriving from the worker class and posting the method that raises the events to the UI thread. The UI class should create an instance of ThreadBarrierWeatherChecker rather than WeatherChecker. This technique is handy if you do not own or can’t modify the code to the worker class.

ThreadBarrier Technique #2: Using extension methods on a SynchronizationContext

This technique requires the developer to not only have access to the WeatherChecker code, but also capture the UI’s SynchronizationContext in the WeatherChecker’s constructor:

private SynchronizationContext _synchronizationContext;

 

public WeatherChecker()

{

this._synchronizationContext = AsyncOperationManager.SynchronizationContext;

}

Raising events now uses the _synchronizationContext field and the ThreadBarrier extension method:

this._synchronizationContext.Post(OnTemperatureChanged, new WeatherEventArgs(Rand(30f)));

this._synchronizationContext.Post(OnWindChanged, new WeatherEventArgs(Rand(15f)));

this._synchronizationContext.Post(OnHumidityChanged, new WeatherEventArgs(Rand(100f)));

ThreadBarrier Technique #3: Deriving from a ThreadBarrier

Again if the developer is in full control of the worker class, all that it takes is deriving from a ThreadBarrier to inherit the method that provides the posting to the UI thread:

public class WeatherChecker : ThreadBarrier

Raising the events is now a matter of calling the Post method in the base ThreadBarrier class:

Post(OnTemperatureChanged, new WeatherEventArgs(Rand(30f)));

Post(OnWindChanged, new WeatherEventArgs(Rand(15f)));

Post(OnHumidityChanged, new WeatherEventArgs(Rand(100f)));

In order for the ThreadBarrier to work the WeatherChecker class needs to be created on the UI thread so the base ThreadBarrier class can capture the UI’s SynchronizationContext.

ThreadBarrier Technique #4: Creating an instance of a ThreadBarrier

If deriving from a ThreadBarrier is not an option, just creating an instance of a ThreadBarrier will work as well. This implementation is similar to the extension method sample, but the ThreadBarrier instance will hide the capturing and storing of the SynchronizationContext. This technique also requires the WeatherChecker to be created on the UI thread.

private ThreadBarrier _threadBarrier;

 

public WeatherChecker()

{

this._threadBarrier = new ThreadBarrier();

}

this._threadBarrier.Post(OnTemperatureChanged, new WeatherEventArgs(Rand(30f)));

this._threadBarrier.Post(OnWindChanged, new WeatherEventArgs(Rand(15f)));

this._threadBarrier.Post(OnHumidityChanged, new WeatherEventArgs(Rand(100f)));

ThreadBarrier Technique #5: Creating an adapter class to propagate events

This technique should be a last resort for the scenario where you can’t derive from the worker class and you are unable to modify its code. Since an extra set of events need to be created and subscribed, it can be dangerous and lead to memory leaks if the handlers are not properly removed.

Adapter Class (extra events removed for compactness)

public class ThreadBarrierWeatherChecker : ThreadBarrier

{

public event EventHandler<WeatherEventArgs> TemperatureChanged;

 

private WeatherChecker _weatherChecker;

 

public ThreadBarrierWeatherChecker()

{

}

 

public void Attach(WeatherChecker weatherChecker)

{

this._weatherChecker = weatherChecker;

this._weatherChecker.TemperatureChanged += new EventHandler<WeatherEventArgs>(_weatherChecker_TemperatureChanged);

}

 

public void Detach()

{

this._weatherChecker.TemperatureChanged -= new EventHandler<WeatherEventArgs>(_weatherChecker_TemperatureChanged);

this._weatherChecker = null;

}

 

void _weatherChecker_TemperatureChanged(object sender, WeatherEventArgs e)

{

Post(OnTemperatureChanged, e);

}

 

protected virtual void OnTemperatureChanged(WeatherEventArgs e)

{

if (this.TemperatureChanged != null)

{

this.TemperatureChanged(this, e);

}

}

}

The adapter class needs to provide a way to attach and detach to an already existing WeatherChecker instance. If the instance is not detached, it will result in a memory leak (the adapter class will be kept alive).

The Original ThreadBarrier Implementation Flaw

The first implementation of the ThreadBarrier used the event as a parameter:

protected void PostEvent<T>(EventHandler<T> eventHandler, object sender, T eventArgs)

where T : EventArgs

{

//do not raise the event if none was provided

if (eventHandler == null)

{

return;

}

 

this._synchronizationContext.Post(delegate { eventHandler(this, eventArgs); }, null);

}

The problem with this implementation is that the event handler delegate is copied when passed to the method. During execution of this method (which occurs on the worker thread) a UI thread could remove the original handler and dispose of the UI control. Since the method’s copy of the delegate will still get posted to the UI thread, the handler will be executed in the control’s code even though the control was already disposed. In other words, if the worker class is being used by multiple windows or controls that are opening and closing it could lead to this problem. See Problem #2 in the Events and Threads post.

ThreadBarrier FAQ

Q: Why not just use AsynchOperationManager.SynchronizationContext in the base class for each method post?
A: Since the methods are originally called on the worker thread, it means the call to the AsynchOperationManager.SynchronizationContext static property will be made from the worker thread. It will thus return an ‘empty’ SynchronizationContext. The call to the static property must be made on the UI and the SynchronizationContext must be ’saved’ so the worker can use it.

Q: Why not just use SynchronizationContext.Current?
A: The static SynchronizationContext.Current returns null when called from a worker thread, while AsynchOperationManager.SynchronizationContext will at least return an empty SynchronizationContext so we at least have some context reference.

Q: What is the difference between a ThreadBarrier and BackgroundWorker?
A: The BackgroundWorker must also be created on a UI thread. However, the BackgroundWorker does not provide an easy and transparent way (other than ReportProgress) to post events and data from the worker to the UI thread. A ThreadBarrier will support any kind of event since it uses generics.

Q: Why not use WPF’s built in cross-thread binding support?
A: A ThreadBarrier can be used in combination with WPF’s cross-thread binding. The difference is that a ThreadBarrier (and events) allow arbitrary code in the UI to execute. Properties just represent data.

Download the examples.

kick it on DotNetKicks.com