I recognize this problem, I debugged a very similar issue back in the Vista days in an unmanaged app. The problem is pretty obscure and is related to the very temperamental WM_ACTIVATEAPP message that you generate by clicking the taskbar button. Particularly when it is dispatched by a nested message loop and that loop does message filtering to allow only certain "safe" messages to be dispatched.
It is caused by the Barrier.SignalAndWait() call. That blocks the UI thread and that is illegal for an STA thread. The CLR does something about it, it pumps its own message loop while the underlying synchronization object is not signaled. If it is that loop that dispatches WM_ACTIVATEAPP, and the odds are pretty high because you block for 30 msec and only pump once, then it goes wrong. For some mysterious reason subsequent messages do not get dispatched. Almost certainly caused by the filtering done by that message loop. Otherwise hard to see, that code was never published and impossible to decompile.
It is fixable, but not easily. The workaround is to force the CLR to not pump this message loop. Which is okay because your waits are short. Something you can do by overriding the SynchronizationContext.Wait() method. Unfortunately that is hard to do, the WindowsFormsSynchronizationContext class is sealed so cannot be derived from to override its Wait() method. You need to visit the Reference Source and copy/paste the class into your code. Give it another name.
I'll give the short version of it, showing what you need to change:
using System.Runtime.InteropServices;
class MySynchronizationContext : SynchronizationContext {
public MySynchronizationContext() {
base.SetWaitNotificationRequired();
}
public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) {
return WaitForMultipleObjects(waitHandles.Length, waitHandles, false, millisecondsTimeout);
}
[DllImport("kernel32.dll")]
static extern int WaitForMultipleObjects(int nCount, IntPtr[] lpHandles,
bool bWaitAll, int dwMilliseconds);
}
And install the new synchronization provider with:
System.ComponentModel.AsyncOperationManager.SynchronizationContext =
new MySynchronizationContext();
In a nutshell, the SetWaitNotificationRequired() call tells the CLR that it should call your Wait() override instead of using its own Wait() implementation. And the Wait() override uses the OS' blocking wait without otherwise pumping. Worked well when I tested it and solved the problem.