I’m trying to make a GUI in QML.jl that does a lot of things asynchronously. In order to improve performance I would like to run Julia with multiple threads since everything is organized into tasks anyway.
But QML.jl doesn’t like multi-threading, randomly giving an undefined reference error (though this is better than what I got with Tk.jl which just crashed Julia).
So since all communications with QML need to be single threaded I was thinking one solution would be to designate a particular thread to do the communicating, but there doesn’t seem to be any particular support for this.
What’s the best way to do this? Can I force particular tasks to run on a particular thread or should I just use a zero/single buffer Channel for force sequential operations?
What you’re asking for is called task pinning, you can do it with the @spawnat macro from StableTasks.jl. I would recommend using a Channel for all the GUI updates and keep one pinned task reading from that Channel and processing the updates. The advantage of doing it with a single task instead of multiple tasks short-lived tasks is that you can easily implement something like logging to check the order in which updates are happening, which can be very useful when debugging.
Thanks a lot!
Though I’m wondering about the Channel, is the reason I should make a channel consumer thread because that’s how Julia advises one to use threads or are there other reasons? I’m also a bit reluctant to do that because I’m trying to make the code accessible to non-experts and that would get complicated quick I think.
Also I notice that @spawnat takes a threadid as input, doesn’t that tie into the discussion mentioned above about threadid being bad?
Ah sorry, I think I misread your message and requirements slightly. If you only want one task touching Qt at once then you don’t even need to worry about task pinning and sticky tasks, you can just launch a regular task as usual with Threads.@spawn (note that the naming is unfortunate, it creates a task rather than OS thread). I mentioned task pinning because doing GUI things on threads other than thread 1 doesn’t really work on macOS but Qt has its own event loop that I assume will take care of thread-safety. Relying on threadid is indeed not the best practice but in some cases it’s unavoidable.
About using a Channel, it’s not necessary and mostly a matter of preference You can also use a lock and ensure that the lock is acquired while communicating with Qt.