Archive for the 'Multithreading' Category

Simple WPF Progress Window with Cancellation

Tuesday, July 22nd, 2008

Original Problem
Many times I have encountered a scenario where all I need to do is perform some small operation that takes a considerable amount of time. If I execute this operation on the UI thread, the UI will block until the operation is complete. Obviously this is not ideal. To address this need, the .NET engineers created the BackgroundWorker class in .NET 2.0. Its purpose is to execute a simple operation on a worker thread, and it does this very well. However, that is only half the battle. If an operation is happening in the background and the user needs to be notified of its progress, the BackgroundWorker must be wired up to some display that displays the progress. In WinForms, developers had many problems initially because they were trying to update controls from the worker thread. .NET 2.0 and later throws an exception if this cross-thread control updating is attempted since it is not allowed in either WinForms or WPF. If you did not know already, all UI controls can only be modified from the thread that created them (the UI thread). There are many examples scattered throughout the internet describing how a developer must ‘post’ the information back to the UI thread before updating a control, such as:

m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText), new object[]{”Text generated on non-UI thread.”});

WPF to the rescue
WPF has come to the rescue with its support for cross-thread property binding and notification. In other words, you can bind a progress bar’s current value to a property that gets changed on another thread. WPF will handle cross thread invoking automatically. This means it becomes very easy to design a WPF window that can not only display the progress of an operation, but also status text and other items that may be updated on the worker thread as an operation progresses, all without having to worry about invoking, callbacks, and threads.

Since most simple operations have the same pattern, a simple interface can be designed that simple operations can implement. We can then design a single WPF window that will display the progress of an operation by attaching to the interface rather than the simple operation:

Once the ProgressWindow and IProgressOperation classes are complete, many simple operations can be designed without having to worry about implementing another UI to display their progress. Here is an example of the IProgressOperation interface:

public interface IProgressOperation
{
int Total { get; }
int Current { get; }
void Start();
void CancelAsync();
event EventHandler ProgressChanged;
event EventHandler ProgressTotalChanged;
event EventHandler Complete;
}

Now we can implement a simple class that exports event logs, and implements this interface. Start() will start the BackgroundWorker, CancelAsync() will set a flag that the operation will check periodically, and the properties Total and Current provide the progress information needed for a progress display.

public void Start()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
public void CancelAsync()
{
this._isCancelationPending = true;
}
public int Current
{
get
{
return this._current;
}
private set
{
this._current = value;
OnProgressChanged(EventArgs.Empty);
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.Total = …

for (…)
{
//exit if the user cancels
if (this._isCancelationPending == true)
{
return;
}
this.Current++;
}
}

Now for the WPF window that will display this IProgressOperation. Since we will make the window implement INotifyPropertyChanged, when the ProgressChanged or ProgressTotalChanged events are raised from the background operation (and coming from a worker thread), we will just raise the events for WPF to update its bindings:

void _operation_ProgressChanged(object sender, EventArgs e)
{
OnPropertyChanged(”Current”);
}
void _operation_TotalChanged(object sender, EventArgs e)
{
OnPropertyChanged(”Total”);
}
public int Current
{
get
{
return this._operation.Current;
}
}
public int Total
{
get
{
return this._operation.Total;
}
}

Finally we have the XAML for the ProgressWindow that shows how it has both progress text and the Progressbar bound to the Current and Total properties that the window exposes to itself from the IProgressOperation.

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”32″/>
<RowDefinition Height=”*”/>
<RowDefinition Height=”42″/>
</Grid.RowDefinitions>
<StackPanel Grid.Row=”0″ Orientation=”Horizontal” HorizontalAlignment=”Center” VerticalAlignment=”Bottom”>
<TextBlock FontSize=”16″>Processing: </TextBlock>
<TextBlock FontSize=”16″ Margin=”5,0,0,0″ Text=”{Binding Path=Current, ElementName=Window, Mode=OneWay}”/>
<TextBlock FontSize=”16″ Margin=”5,0,5,0″>of</TextBlock>
<TextBlock FontSize=”16″ Text=”{Binding Path=Total, ElementName=Window, Mode=OneWay}”/>
</StackPanel>
<ProgressBar Grid.Row=”1″
Width=”200″
Height=”20″
Value=”{Binding Path=Current, ElementName=Window, Mode=OneWay}”
Minimum=”0″
Maximum=”{Binding Path=Total, ElementName=Window, Mode=OneWay}”></ProgressBar>
<StackPanel Grid.Row=”2″ Orientation=”Horizontal” HorizontalAlignment=”Center”>
<Button Margin=”6,6,6,6″ Width=”80″ Height=”30″ Click=”CancelClick”>Cancel</Button>
</StackPanel>
</Grid>

How do we start the operation and display the ProgressWindow? It is just a matter of creating a new ProgressWindow and passing in the IProgressOperation into its constructor:

ProgressWindow progressWindow = new ProgressWindow(new EventLogExporter());
progressWindow.ShowDialog();

The ProgressWindow will call the Start() method on the IProgressOperation once the window has completely loaded.

Keep in mind that this ProgressWindow is a very simple example demonstrating the power of WPF and binding. It can easily be extended to display many other items such as status text or other information, all using binding and not having to worry about invoking on the UI thread. You can also use the concepts provided in this article to design your own more powerful and customized ProgressWindow.

Sample: SimpleWPFProgressWindow

Subtle Multithreading Bugs – Part 1

Tuesday, July 22nd, 2008

There are many aspects to multithreaded software design and development that can make it very difficult. I have come across several subtle bugs that can easily bite you if you are not careful. Since many developers may never find a “do not do this” guide that includes these subtleties, I will be explaining them with the hope of helping you improve your multithreading capabilities.

Part 1 is in regards to working with thread-safe collections. There are many ways to make a thread safe collection, such as rolling your own, deriving from a collection and wrapping access to the underlying collection via locks, or using the thread-safe framework collections. We will use the framework’s thread-safe queue in today’s example.

Queue myThreadsafeQueue = Queue.Synchronized(new Queue());

That is how easy it is to make a thread-safe queue. It is just as easy to make a thread-safe list using ArrayList.Synchronized. Sorry, there are no built in thread-safe generic collections (but it is not too difficult to create your own by deriving from a generic collection). So what is a thread-safe collection? It basically means that if you were to execute the following from two different threads, the collection will internally lock on an object and only allow one method to execute at a time:

myThreadsafeQueue.Enqueue(new object());

All method and property calls can therefore be safely called from multiple threads. The real danger that can be difficult to see is when a collection needs to be enumerated. Consider the following way to work on a queue:

while (myThreadsafeQueue.Count > 0)
{
object myObject = myThreadsafeQueue.Dequeue();
//do some work with myObject
}

Do you see the bug? I’m sure the veterans do. The flaw is that between the call to get the Count and the call to Dequeue() an object, another thread could have cleared out the queue. This would mean that when the above code executes, the call to Dequeue() will occur with an empty queue and will thus throw an exception. The solution is to lock on the collection’s SyncRoot object while enumerating:

lock (myThreadsafeQueue.SyncRoot)
{
while (myThreadsafeQueue.Count > 0)
{
object myObject = myThreadsafeQueue.Dequeue();
//do some work with myObject
}
}

Since the SyncRoot object is the object that the collection internally uses to perform synchronization, if the Clear() method is called on the collection from another thread, that thread and method call will block until the Lock(myThreadsafeQueue.SyncRoot) finishes executing. The general rule is as follows:

“Any time a collection is being enumerated, to maintain thread safety, all collection operations should be wrapped in a lock using the SyncRoot object.”

If this rule is not followed, weird exceptions can occur. For example, if you do a ‘foreach’ loop on a thread-safe ArrayList and another thread modifies the collection, you can get the error:

InvalidOperationException: “Collection was modified; enumeration operation may not execute.”

A sample is attached that demonstrates the correct and incorrect way to access a queue safely from multiple threads. Note: If you do decide to derive from a generic collection, it is best to internally lock using the already existing ICollection.SyncRoot object.

Sample: SubtleMultithreadingBugs

WPF Cross-Thread Collection Binding – Part 4 – The Grand Solution

Tuesday, July 22nd, 2008

The Grand Solution – Thread safe binding to a collection and properties that are modified from any thread.

History
-WPF supports cross thread property change notification.
-WPF does not support cross thread collection change notification.
-Part 1 introduced the ObservableBackgroundList<T> that allows cross thread collection change notification from a single worker thread.
-Part 2 described WPF’s lack of support for cross thread property change notification for items that are in the cross thread collection binding.
-Part 3 introduced a solution that allows cross thread property change notification from any thread for the items in the cross thread collection binding.

We are now ready to make the final leap and introduce a solution that supports binding to a collection that can be modified from any thread (including the UI thread). The class is called ObservableList<T>. Here is how to use it:

1. Pass in the UI’s Dispatcher to the constructor
2. Bind to the ObservableCollection property
3. Use the list from any thread by wrapping all list operations in a using block that utilizes the method AcquireLock.

The ObservableList is made thread-safe by acquiring a lock before accessing the list (including just reads). The AcquireLock method is the way to lock the list and prevent other threads from modifying the list while the list is being accessed by the thread owning the lock. Below is a screenshot of a sample application that demonstrates simulating a server that has many worker threads that update the collection and modify properties.

This is an example of how to wrap all list operations in a using block where _activeTasks is an ObservableList<Task>:

using (TimedLock timedLock = this._activeTasks.AcquireLock())
{
foreach (Task task in this._activeTasks)
{
task.PercentComplete = 100;
}
}

The TimedLock is an IDisposable class that locks on an object passed into its constructor and then unlocks when the TimedLock is disposed. ‘Using’ ensures that no matter what happens inside the using parenthesis, the IDisposable.Dispose() method will be called on the TimedLock, thus releasing the lock. If any single thread has acquired the TimedLock then all other threads will block (provided they follow the same pattern). Even the UI thread must acquire the lock before accessing the ObservableList (but WPF does not need to lock on the ObservableCollection). The TimedLock was taken from IanG’s blog and is nothing more than a lock with a timeout to help debugging scenarios.

Quiz for the experts: In the ObservableList<T> all change requests are always posted to the UI thread via the Dispatcher, even when the UI thread is the thread accessing the list. Why did I design it so the UI thread takes a performance hit and still posts change requests to itself? One might think that when the UI thread is executing, all change requests from other threads are automatically blocked until the UI is done, so it should be safe to update the list directly. This turns out to be false. I myself am not a threading guru, but if anyone gets the right answer you can wear that award :)

We now have solution with the following features:

Features
-Allows WPF to bind to a collection that is modified from any thread
-Allows WPF to bind to properties of items in the collection that are modified from any thread
-No lock required if used from a single worker thread
-Relatively simple (compared to some other attempts)
-Non-blocking

Downsides
-Requires two lists internally
-The ObservableCollection list should not be modified
-Disposable or DependencyObjects should not be used

Despite these negatives, the community now has a solution to suit developers’ WPF, binding, and multithreading needs.

Disclaimer: Although I spent a considerable amount of time studying and testing the design and concepts described in this series, as well as beating the heck out of the ObservableList<T> with a quad core CPU and 10+ threads each modifying the collection and properties at full speed, I am still human and this is just a blog post. Do your own research and testing, and as always, use at your own risk. I will keep this post updated if there are any issues. I personally believe we can put this topic to rest until WPF adds native support for all of these features.

UPDATE: Microsoft has recognized the property/collection change race condition bug and will fix it in a future version of the framework.

Download the Sample: MultithreadedObservableListSample

WPF Cross-Thread Collection Binding – Part 3 – Working Property Change Events

Tuesday, July 22nd, 2008

Property Change Notification from Worker Threads Solution

Update: The final solution has been posted.

Part 2 described why you should not modify properties of items in a collection that is on a worker thread. The solution is to listen for the events ourselves and then raise the PropertyChanged event from the UI thread. If we can do this, property and collection change events will be raised on the UI thread, WPF will be happy, and everything will work. The first step to catching the property change event is to create a new interface:

public interface ICollectionItemNotifyPropertyChanged : INotifyPropertyChanged
{
event PropertyChangedEventHandler CollectionItemPropertyChanged;
void NotifyPropertyChanged(PropertyChangedEventArgs e);
}

Items in our collection now must implement ICollectionItemNotifyPropertyChanged such as:

public class Task : ICollectionItemNotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler CollectionItemPropertyChanged;
public int PercentComplete
{
get { return _percentComplete; }
set
{
_percentComplete = value;
OnCollectionItemPropertyChanged(”PercentComplete”);
}
}
public void NotifyPropertyChanged(PropertyChangedEventArgs e)
{
OnPropertyChanged(e);
}
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
protected void OnCollectionItemPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.CollectionItemPropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Now when the ObservableBackgroundList gets a request to add or remove an item from its ObservableCollection, it can attach to the CollectionItemPropertyChanged event. When that event is raised (from any thread) the handler will always post to the UI thread a method that will raise the PropertyChanged event.

private void StartListening(T source)
{
ICollectionItemNotifyPropertyChanged item = source as ICollectionItemNotifyPropertyChanged;
if (item != null)
{
item.CollectionItemPropertyChanged += new PropertyChangedEventHandler(item_CollectionItemPropertyChanged);
}
}
private void StopListening(T source)
{
ICollectionItemNotifyPropertyChanged item = source as ICollectionItemNotifyPropertyChanged;
if (item != null)
{
item.CollectionItemPropertyChanged -= new PropertyChangedEventHandler(item_CollectionItemPropertyChanged);
}
}
void item_CollectionItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this._dispatcher.BeginInvoke(DispatcherPriority.Send,
new PropertyChangedCallback(PropertyChangedFromDispatcherThread),
sender,
new object[] { e }
);
}
private void PropertyChangedFromDispatcherThread(T source, PropertyChangedEventArgs e)
{
ICollectionItemNotifyPropertyChanged item = source as ICollectionItemNotifyPropertyChanged;
item.NotifyPropertyChanged(e);
}

Here is a diagram that shows how CollectionItemPropertyChanged events are caught and used to raise PropertyChanged events from the UI thread:

Now all PropertyChanged events are raised from the UI thread and there are no threading issues to worry about. We can even raise the CollectionItemPropertyChanged events from any number of workers, but the collection can still only be modified from one worker. The following sample demonstrates these concepts in action.

ObservableListSample1

Update: The final solution has been posted.