Using AsyncUpdater in a windows DLL


I’m using JUCE as an audio engine (dll) inside a Windows app (flutter), and I can’t get AsyncUpdater to work properly. Any other JUCE code works fine.

I tried to get an understanding of the JUCE code, and also compared it to the macOS version of the app (where my JUCE lib is linked statically), so here’s what I found:

The first time I call triggerAsyncUpdate a message gets posted “somewhere” (I stepped through the code all the way to a native windows API function PostMessage). I assume here the message is posted to the “main thread”.

void AsyncUpdater::triggerAsyncUpdate()
// If you’re calling this before (or after) the MessageManager is
// running, then you’re not going to get any callbacks!

if (activeMessage->shouldDeliver.compareAndSetBool (1, 0))
    if (! activeMessage->post())
        cancelPendingUpdate(); // if the message queue fails, this avoids getting
                               // trapped waiting for the message to arrive


On my macOS version, the next thing that would happen is AsyncUpdater’s message callback being called from the Apple main thread, which would call my implementation of handleAsyncUpdate(), and “unlock” the shouldDeliver field.

void messageCallback() override
if (shouldDeliver.compareAndSetBool (0, 1))

However, on Windows the messageCallback is never called, so my subsequent calls to triggerAsyncUpdate won’t get past this condition:

if (activeMessage->shouldDeliver.compareAndSetBool (1, 0))

Now, I can see that the only place messageCallback() is called on Windows is inside the MessageManager::runDispatchLoop(), which seems to be run only inside JUCE standalone apps. Is that right?

What I don’t understand is, if there’s a way that these messages posted by the AsyncUpdater’s triggerAsyncUpdate() can be “consumed” (i.e. messageCallback() → handleAsyncUpdate() → shouldDeliver = 0) by some event loop other than MessageManager::runDispatchLoop()?

Right now my DLL entry point is being called from the flutterUI thread (which is not the Windows app main thread). Doing that requires some ugly wiring.

Should I expect calling initialiseJuce_GUI() from the main thread to solve my issue? Would that help JUCE link to the app’s event thread which will run a ‘event dispatch loop’ itself similar to the one that’s implemented in JUCE as MessageManager::runDispatchLoop()?

I hope this makes sense :sweat_smile:

p.s. I did call the juce::Process::setCurrentModuleInstanceHandle() with the correct value HINSTANCE

I’ve seen a lot of posts around this topic. Here’s one that seems relevant, where Jules suggests that initialiseJUCE should be called from the main thread:

nevermind… In the end I did call the init functions from the app main thread and everything works fine

The HiddenMessageWindow procedure was never being called before