Windows forms application blocks after station lock
- by Silviu
We're having a serious issue at work. We've discovered that after the station where the client was running is locked/unlocked the client is blocked. No repaint. So the UI thread is blocked with something. Looking at the callstack of the UI thread (thread 0) using windbg we see that a UserPreferenceChanged event gets raised. It is marshalled through a WindowsFormsSynchronizationContext using it's controlToSend field to the UI. It gets blocked by a call to the marshalling control. The method called is MarshaledInvoke it builds a
ThreadMethodEntry entry = new ThreadMethodEntry(caller, method, args, synchronous, executionContext);
This entry is supposed to do the magic. The call is a synchronous call and because of that (still in the MarshaledInvoke of the Control class) the wait call is reached:
if (!entry.IsCompleted)
{
this.WaitForWaitHandle(entry.AsyncWaitHandle);
}
The last thing that i can see on the stack is the WaitOne called on the previously mentioned AsyncWaitHandle.
This is very annoying because having just the callstack of the runtime and not one of our methods being invoked we cannot really point to a bug in our code.
I might be wrong, but I'm guessing that the marshaling control is not "marshaling" to the ui thread. But another one...i don't really know which one because the other threads are being used by us and are blocked...maybe this is the issue. But none of the other threads are running a message loop. This is very annoying.
We had some issues in the past with marshaling controls to the right ui thread. That is because the first form that is constructed is a splash form. Which is not the main form. We used to use the main form to marshal call to the ui thread. But from time to time some calls would go to a non ui thread and some grids would broke with a big red X on them. I fixed this by creating a specific class:
public class WindowsFormsSynchronizer
{
private static readonly WindowsFormsSynchronizationContext = new WindowsFormsSynchronizationContext();
//Methods are following that would build the same interface of the synchronization context.
}
This class gets build as one of the first objects in the first form being constructed.
We've noticed some other strange thing. Looking at the heap there are 7 WindowsFormsSynchronizationContext objects. 6 of these have the same instance of controlToSend, and the other one has some different instance of controlToSend. This last one is the one that should marshal the calls to the UI.
I don't have any other idea...maybe some of you guys had this same issue?