3
votes

I have a Windows Forms program that hosts several WPF controls. It is a test execution tool. We have come across an issue where Invoke calls never return. This is happening for one of the tests plans written by one of our users.

The problem happens at different Invokes throughout the program. Two examples:

winForm.Invoke(new Action(() => wpfControl.DataContext = something));
Application.Current.Dispatcher.Invoke(new Action(() => result.Container.Clear()));

The thread calling Invoke never returns from the Invoke. I expected there was deadlock with the GUI thread, but the GUI thread is executing fine. Interestingly, all WinForm controls are behaving normally, but no WPF controls respond to the user. None of the other worker threads seem to be blocked.

Two questions come to mind:

  1. Does anyone have any debugging suggestions?
  2. Why would all WPF controls be blocked but all WinForm controls work fine?

Edit: I should have mentioned that this is may be a race condition of some sort. It is seen very infrequently and only after the application has been working normally for a while.

3
I don't know exactly what is going on, but you have too little information here to go on. You should get either dotpeek or reflector, and put a breakpoint in WPF internal "loop", and see WHY it is not updating / why it is not called. The most powerful technique in debugging is to actually debug the internal code. I would be also interesting to see what happens if you use Snoop tool.Erti-Chris Eelmaa
how do you say all WinForm controls are behaving normally ? In you code if winForm.Invoke does not return to the next line then the whole application should not respond.Vignesh.N
Setting the DataContext should be done in the same thread as the one in which the WPF control was created are you are sure that is the case ? Also try BeginInvoke insteadVignesh.N
Are you sure that WPF Dispatcher has started?Marat Khasanov
@ChrisEelmaa your suggestion for debugging is exactly what I was looking for as a next step. I haven't debugged internal code before. I will try that next time I can look at this problem. It only occurs once every few thousand hours of application run time. If you make your edit an answer, I would assign the bounty points to it.GreenRibbon

3 Answers

2
votes

I don't know exactly what is going on, but you have too little information here to go on. You should get either dotpeek or reflector, and put a breakpoint in WPF internal "loop", and see WHY it is not updating / why it is not called.

The most powerful technique in debugging is to actually debug the internal code. I would be also interesting to see what happens if you use Snoop tool.

Invoke itself is very good recipe for dead locks. I've encountered myself deadlocks, I've seen others encounter it, etc.. If possible, see if you can get away with BeginInvoke.

1
votes

You need to invoke (dipatch) by control itself.

use this code wpfControl.InvokeIfRequired(() => wpfControl.DataContext = something); And this wpfControl.InvokeIfRequired((() => result.Container.Clear())

public static void InvokeIfRequired(this DispatcherControl control, Action operation)
{
  if (control.Dispatcher.CheckAccess())
  {
    operation();
  }
  else
  {
    control.Dispatcher.BeginInvoke(DispatcherPriority.Normal, operation);
  }
}
0
votes

If I understand the question correctly you have a Windows Forms on which you host WPF controls.

First of all why would you do something like that?

Windows Forms have Window Controls
WPF has WPF Controls.

Lately I read that it is possible from WPF to host WF forms. source (Pro WPF 4.5 in C#, 4th Edition)

If I am not mistaken the WPF controls run in their own thread. In contrary to the WF controls. This could give a lock in the WPF controls.

Nb. If people are downvoting atleast have the guts to go in discussion about why.