Not sure if this is still an issue for you anymore but I've figured out what causes this.
When a juce::Thread is created in Windows it calls AttachThreadInput() on the new thread (I'm guessing to allow manipulating any window on any of the threads or something). This essentially serializes all input from windows on any juce threads and the main thread.
When you call MessageBox() on a thread created by juce (or any thread whos input is attached), the message box's input will be serialized with input on the main thread. So basically if the message box has some message waiting to be handled, your app's messages are held hostage until the message box processes its message. If the message box doesn't process the message, your app won't get any more messages.
At first glance this seems like it should be okay (although not ideal) since the message box closes and it should stop getting messages. However, I've found that there usually is a message left on the message box's queue after you close it. The message is something related to multilingual/language bar or something like that, so it might be possible that not all systems will get this message.
There are a couple of ways I've found to work around this:
1. Don't use AttachThreadInput() (Either turn it off after starting the thread, or surround your MessageBox call with code to turn it off and on again).
2. Flush any remaining messages from the message box.
Something like this after the message box call would flush it:
while (PeekMessage (&message, (HWND) 0, 0, 0, PM_REMOVE) != 0)