I work on a WPF application. I have the following code:
But I never get to the breakpoint that is put at the beginning of ExpandFreeDraw method:
When I invoke the BeginInvoke method, I'm already on the UI thread:
The ExpandFreeDraw method should also happen on the UI Thread. I invoke it with priority of context idle for the following reason:
Before the line of BeginInvoke, I change the Visibility of a WPF Expander from collapsed to Visible. It starts rendering its controls: some of those controls are input controls and I want to apply validation to them (done via AdornerDecorator which makes it look like the input control has a red validation border). If I call the ExpandFreeDraw directly after changing the visibility of the Expander (just ExpandFreeDraw() without Dispatcher), I do get to the breakpoint at the beginning of the ExpandFreeDraw method: the expander is visible but the adorner is not applied correctly - no red border effect.
I get the same effect with Dispatcher.BeginInvoke with the next lower priority, which is background:
In that case, I also get to the breakpoint at the beginning of the ExpandFreeDraw method. When I apply the next priority, which is ContextIdle, then my issue is reproduced - I don't get to the mentioned breakpoint.
Note that this functionality works most of the time, and that's how I know the ContextIdle priority is my desired priority, because it does apply the validation to input controls in most of the cases (if I reduce the priority to Background, it already doesn't). That is because the priority given to the Dispatcher is ContextIdle which is lesser that Render - You can read more about it here: http://www.jonathanantoine.com/2011/08/29/update-my-ui-now-how-to-wait-for-the-rendering-to-finish/).
I would like to get some help on how to figure out what is the problem. Why is
invokes the method of ExpandFreeDraw correctly in most of the cases, but in one of the scenarios (which I can't really understand which) it doesn't? How can I debug it?
Maybe:
Could it be that the background operations are never completed? And that's why the operation with ContextIdle priority is never executed? How can I figure it out?
I've finally solved it. My issue was that the UI dispatcher queue kept constantly getting actions with a higher priority (higher than context-idle).
If you write a code as the following:
public MainWindow()
{
InitializeComponent();
Thread t = new Thread(() =>
{
Application.Current.Dispatcher.BeginInvoke(new Action(() => DoBackGround1()), DispatcherPriority.Background, null);
Application.Current.Dispatcher.BeginInvoke(new Action(() => Debug.WriteLine("Context-Idle")), DispatcherPriority.ContextIdle, null);
Application.Current.Dispatcher.BeginInvoke(new Action(() => Debug.WriteLine("Additional-Background")), DispatcherPriority.Background, null);
});
t.Name = "dispatcherTest";
t.Start();
}
private void DoBackGround1()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
Debug.WriteLine("Background " + i);
}
}
You will get the following result in the output window:
Background 0
Background 1
Background 2
Background 3
Background 4
Background 5
Background 6
Background 7
Background 8
Background 9
Additional-Background
Context-Idle
Additional-Background action is performed before the context-idle action, even though it was queued into the UI queue dispatcher after the context-idle action. It's trivial, but it is important to understand this concept.
I had a code that checks if I'm on the UI thread - If so, perform the action immediately. Otherwise, queue it into the dispatcher queue. When I forced the mentioned action (ExpandFreeDraw) into the UI queue (even if I was already on the UI thread), it all worked for me: now the action is invoked and I also get the needed validation.