Right way to trigger UI changes from background threads?


#1

I’ve got a couple background threads that talk to a server and I’m trying to understand the best way to cause the results of those thread activities to trigger GUI changes, like a dialog box popping up, etc. I read quite a bit about not using MessageManager::callFunctionOnMessageThread() from any background threads, so i’m at a bit of a stopping point figuring out how to get this to work without blocking.

What i’ve got happening in my app is when the user clicks on a menu item, a window appears which spawns a couple background threads to retrieve some data from a server. Those threads trigger callbacks in the window to populate the window’s objects with the data. When the user selects one of the objects and clicks a button in the window, the threads for talking to the server are started up again. when those threads finish what they’re doing, they trigger callBacks to the window, which result in Save dialog boxes. The problem i’m running into is that these server threads are the ones that are triggering these dialog boxes, which you can’t do as they’re not the MessageManager thread.

What’s the correct way to tell the MessageManager to do some UI things (dialog boxes, save windows, etc) from threads other than the MessageManager thread?


#2

AsyncUpdater will suit your needs. You could also use MessageManager::callFunctionOnMessageThread(), not sure why you wouldn’t want to call it from background threads as that is its entire purpose.


#3

Pretty much every post where someone asks about using it, @jules says don’t use it and he’s not sure why he wrote it lol


#4

Ah okay, I just read the documentation. callFunctionOnMessageThread() blocks until its code has been run, so if you have multiple threads using that system while also sharing an exclusive resource, you can easily deadlock.

Go with AsyncUpdater.


#5

MessageManager::callAsync may do what you need, but you need to be careful that events don’t get delivered after their target component has been deleted. AsyncUpdater is safest.


#6

Almost everytime I use callAsync I shoot myself in the foot with some kind of object-no-longer exists bug :wink: You’d have thought one mistake might be enough to learn my lesson, but it’s more like five and counting…


#7

Is this callAsync method new? it’s definitely not in JUCE 4.2.4…

JUCE-4.2.4/doxygen/doc/functions_c.html#index_c


#8

Ah, it’s not showing up in the website docs because it’s C++11 only… We should fix that! But no, it’s not new, and you can see it if you look at the code.


#9

C++11 functions and classes are now visible in the online docs.


#10

aah… If only the official docs were searchable…

https://bill-auger.github.io/JUCE/doxygen/doc/classes.html

Cheers,

Rail