Execute.OnUIThread & Performance (Silverlight)

Apr 14, 2011 at 2:55 PM

There may be specific circumstances that cause this issue to surface, but I want to raise the issue here just in case someone else runs into the same problem.

In the Silverlight version, Execute.OnUIThread pauses the thread while it executes the action. This has the effect of causing the action being marshaled to run synchronously. Overall, this provides a more intuitive experience for the consuming developer.

I had a scenario though in Raven Studio where the thread was being blocked for a significant amount of time. Specifically, I was binding a BindableCollection with about 120+ items to an ItemsControls. Rendering these items sometimes took 2 to 5 seconds. Profiling revealed that the problem was the thread being blocked when using Execute.OnUIThread. The exact spot in Raven where I had the problem is here.

In my case, I forked Caliburn Micro and removed the bits that paused the thread. This change had side-effects and I had to make changes to BindableCollection as well. The changes are here and here.

If anyone has any additional insight, or alternatives to my solutions, I would be interested.



Apr 14, 2011 at 3:15 PM
Edited Apr 14, 2011 at 3:16 PM

I would strongly discourage you from removing thread affinity between collection insertion and notification in BindableCollection.

There is at least one post where the approach you are using can cause issues. My comments are based on post from Beatriz Costa related to the implementations proposed by Kent Bogaart and Chong.

In case of large collections, the proper approach is performing the insertion in small 'buckets', so that the UI does not freeze.

You could define a proper collection that performs bucketed insertions using a DispatcherThread (the idea is to insert only small chuncks and let the Dispatcher do more work while the complete set is added to the collection and thus to the visual tree).

Apr 15, 2011 at 12:01 AM
Edited Apr 15, 2011 at 12:01 AM

I don't see anywhere in that code where you are actually adding things to a bindable collection. Is it in BindablePagedQuery? It might be something that can easily be fixed by using AddRange. Otherwise, you'll want to handle things differently. You probably don't want to remove the marshalling from that collection...it could have negative effects.

Apr 15, 2011 at 12:06 AM

Ok. I see that it was in add range. Well, I wouldn't change the base implementation. That would likely cause a lot of issues and it would not be consistent with what developers would expect...that is that AddRange is expected to be a blocking call. Consider inheriting from BindableCollection<T> and adding a custom method which does not do the sync. or create a new collection for your needs. But, changing the existing implementation is likely to cause serious issues with thread sync.

Apr 15, 2011 at 12:52 AM

@BladeWise I'll pour over the posts you recommended this weekend. Thanks. Also (and maybe this is in the Beatriz post) what is the reason for inserting on the same thread as the change notification? I'd also be curious to know what scenarios caused the inverse order problem.

@EisenbergEffect what sort of scenarios do you expect would thread sync issues? 

So far, performance has greatly improved and I've seen no adverse side-effects.

Apr 15, 2011 at 2:15 AM

You can find some of the problem descriptions by digging through the forums. We used to have the behavior you reverted to, but it was changed to the present behavior becuase of numerous bugs that could be introduced that way. We even encountered bugs related to it on some of Blue Spire's work. At that time I just worked around it. But when I saw other users hitting issues in multiple scenarios, I changed the implementation to the more intuitive form that it has now. Not knowing whether the items you added will be present in the collection after you call add can cause issues. The same thing can happen with normal INPC where changing the property doesn't notify until some unknown point in the future. 

Apr 15, 2011 at 1:07 PM
Edited Apr 15, 2011 at 1:09 PM

@bennage: every time you update your collection from a thread that is not a Dispatcher thread you can incour in a problem. To be more specific, since you can add items into the collection asynchronously, then dispatch the notification, it is possible that other parts of the WPF framework access to the updated collection before all the elements involved in the UI representation have been notified. In my case, I noticed that a list bound to such collection had duplicated visual elements.

The fact is that if you notify and dispatch synchronously, you are confident that the WPF pipeline has all the information required.

When you speak of 'performance' you are only referring to the perceived responsiveness of your UI. When you decouple collection modification and notification, probably you are using two different Dispatcher cycles while the default implementation uses a single one.

To understand the difference between the approaches, consider the following example:

var myCollection = new BindableCollection();
Debug.Assert(myCollection.Count == 1);

1. In the current implementation, the following code may fail if the thread executing such code is not the Dispatcher. This forces people to ensure thread affinity on the VM, thus ensuring that race conditions are avoided.

2. In your implementation, the same code cannot fail, and hides the fact that there is some thread synchronization to be dealt with. If you ignore this fact, there is a chance that the UI layer 'sees' a callection which is different from the expected one. This can lead to effects similar to race conditions, since objects listening to the collection notification are not synchronized with the collection itself.

Probably this is not the best explanation of the issue, but I suppose I gave you enough hints to think about it.

On a final note, you can consider that since the VM is just a model of the View, you need to ensure that VM code is thread safe.

Apr 15, 2011 at 1:22 PM

For those following this discussion. Here is the significant bits, copied from the comments on Chong's blog mentioned in the first response. Also, note that this is specifically with respect to WPF (though I don't think that makes a difference).

Hi Chong,

I see at least one serious bug in the solution from your blog (also in the solution from Kent's blog). It applies to all operations, but let's take Insert as an example. Your method inserts the new item into the data structure on the worker thread, then raises the change notifcation on the dispatcher thread (blocking the worker thread until the dispatcher thread is available). So there's an interval of time where the item has been added, but the dispatcher thread doesn't know it yet. If the dispatcher thread reads the collection during this interval, it will get the wrong information. This can lead to incorrect display, or even a crash.

The solution in Bea Costa's blog does both the actual insertion and the notification on the dispatcher thread, so it doesn't have the problem.

Sam Bent and Bea Costa

To which Chong replies:

As I mentioned in my post, my solution is not thread safe so I am aware of the problems you have mentioned.

My solution will work only under the following conditions.
1. A worker thread is updating the collection.
2. The UI thread is only using data binding to display the collection.
(This is what is required in my current project and that is why I come up with the simple solution)

For more complex condition, say multi threads can update the collection at the same time, my solution won't work, more work need to be done to make it thread safe.

Apr 15, 2011 at 1:31 PM

@BladeWise Thanks, and my apologies for cross-posting. I appreciate you trying to explain the circumstances that can actually cause the problem.

Regarding your statement about the term 'performance': yes, I do mean responsiveness of the UI. However, what I was specifically dealing with was the following code blocking a thread for several hundred ms:

else {
	var waitHandle = new ManualResetEvent(false);
	Exception exception = null;
	dispatcher.BeginInvoke(() => {
		try {
		catch(Exception ex) {
			exception = ex;
	if(exception != null)
		throw new TargetInvocationException("An error occurred while dispatching a call to the UI Thread", exception);

Apr 15, 2011 at 1:35 PM

Oh I forgot to say. My first attempt to solve the problem was a 'bucketing' solution. However, I still had issues with the code above blocking.

I'm going to guess that the next recommendation will be to find out what other bit was contending with the above so much.

Apr 15, 2011 at 3:20 PM

Note that the Chong answer is not that meaningful: he says that the solution works in the proposed context, where a single worker thread writes and the Dispatcher reads. Unfortunally, this is not true. Bea explicitly says that even in such scenario the behaviour of the framework on the Dispatcher cannot be predicted, so even in such simple scenario, that approach may fail. She is not speaking about multiple worker threads updating the collection, but about the interaction between the Dispatcher and every asynchronous thread.

Regarding your analysis with the profiler: in your case a thread is stalled while the Dispatcher is running. The profiler points out that a resource (the worker thread) is 'wasting time' waiting, and thus that part is considered critical. Unfortunally, such waste of time cannot be avoided to ensure thread affinity. The only possibility is to reduce the time 'wasted' by the Dispatcher processing.

As you guessed, I would check which part of code is taking so much time to be processed on the Dispatcher. It could be part of your application logic (e.g. adding an item to the collection will trigger more operations on your logic layer) or the UI (e.g. you are displaying items on an ItemsControl, not all items are visible at the same time, but there is no UI virtualization, so the complete UI is processed even if it shouldn't).

A bit more information regarding your scenario (or a simple repro) could help me to provide a more meaningful solution. :)

May 24, 2012 at 8:40 AM
pauli7 wrote:

In order to prevent cross-thread-exceptions I therefore dispatch each incoming message on the UI thread via Execute.OnUIThread. While processing the 1st message from the background thread on the UI thread, the background thread is suspended due to the use of ManualResetEvent in Execute.OnUIThread.

I suppose that this design is intrinsecally flawed, since it delegated to the UI thread some processing that should be processed in the background.

Note that property change notification thread affinity is ensured by the framework (i.e. you can change a property in a thread different from the UI, and the framework will automatically dispatch it on the relvant UI thread), while collection change notification thread affinity are handled by CM's BindableCollection<T>. In other words, if your background processing is simply changing properties and modifying collections, you can avoid to dispatch the entire processing to the UI thread, since relevant bits are automatically dispatched.

Now, since messages should be processed in the order of arrival, I would separate message receive from thei execution on two different threads:

  • the receiving thread will keep on listening on incoming Https messages, and store them into a queue as soon as received
  • the processing thread will be executed every time the first message is put into the queue, and will keep on running until he is able to dequeue a message

this approach requires proper synchronization between receiving and processing thread, but allows for complete separation between the communication layer and the processing layer (this means that you could always increase the number of receiving or processing threads, without affecting the overall design). Note that this is a typical approach when dealing with sockets or low level communication.

Your current design uses the UI thread as a processing thread, and uses naive synchronization between the listening thread and the processing thread (i.e. stop listening while executing), which is extremely poor in term of performances. If incoming messages are enqueued in a thread-safe collection (I mean that the collection can be safely accessed by multiple threads), the receiver can keep on receiving and push in the queue asynchronously, while the processing thread (which should never be the UI thread) is able to access the queue and start handling the messages one by one (if needed, you could even use multiple threads for processing, it depends on how much parallel processing you want/can do). Note that the executing thread could still dispatch on the UI thread, but you should be careful when doing this, since intensive jobs could lock up your UI...