Today I stumbled upon an error in WPF: “Cannot perform this operation while dispatcher processing is suspended”. Here is the story why it happened.
Controls in application have custom inherited attached property MyInheritedAttachedProperty. Which is tracked for changes. When it is changed there was need to pump all pending operations in Dispatcher (as it’s described in this MSDN article) with helper method DoEvents:
1 2 3 4 5 6 7 8 9 10 11 12 |
public static void DoEvents(this Application application) { DispatcherFrame frame = new DispatcherFrame(); Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame); Dispatcher.PushFrame(frame); } private static object ExitFrame(object frame) { ((DispatcherFrame)frame).Continue = false; return null; } |
There was MyCustomControl with MyInheritedAttachedProperty attached to it. This control has different templates applied depending on IsReadOnly property. Next steps has led to error:
- Value of MyCustomControl.MyInheritedAttachedProperty changes from default 0 to 1.
- As it is inherited attached property all controls in Visual Tree get this value.
- Value of MyCustomControl.IsReadOnly changes to true.
- Visual Tree for control is replaced with new one.
- WPF makes layout, measures, arranges, refreshes bingings and assigns whole bunch of inherited attached properties.
- There is a TextBox in ReadOnly-template which now is in new Visual Tree and MyInheritedAttachedProperty has changed for it instantly after it has been added.
- As you remeber DoEvents method is called when MyInheritedAttachedProperty changed. DoEvents calls Dispatcher.PushFrame() which is prohibited to call during WPF layout operations.
It was my error. There was no need to call DoEvents as many times as control count in Visual Tree.
At the end of the story I had found the way that allowed to make same things without using DoEvents and let WPF do its job.
The moral of this story: Do not call Dispatcher.PushFrame() from property changed event.