Qt and Maya both want the main thread...what to do?

528 views
Skip to first unread message

Michael Boon

unread,
Mar 23, 2015, 8:57:01 PM3/23/15
to python_in...@googlegroups.com
Hi,

I have a few PySide tools that are multi-threaded and in general they work well. However, I can't figure out how to correctly make Maya do complex operations while keeping my Qt GUI responsive. Both systems insist on only being run from the main thread.

The Qt documentation says "The Qt GUI must run in this [the main] thread."
And the Maya documentation says "Maya commands throw an exception if they are called outside the main thread"

Is there a good way around this?

(Really all I want is to have a cancel button that will react immediately.)

Thanks,

Boon

Justin Israel

unread,
Mar 23, 2015, 9:46:50 PM3/23/15
to python_in...@googlegroups.com
If your goal is to keep your GUI reacting quickly, you can defer the call to the event loop. This will allow your button to fully click. Then the callback will run when control returns to Maya's event loop:

maya.utils.executeDeferred()

Ideally you are doing as much heavy lifting as you are able to to, in extra threads. But in the case where things must run in the main gui thread, your best bet is to defer them until after your gui can finish responding to the user interaction.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/e74b8d33-5db7-44f1-a58c-65ba549aaafb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michael Boon

unread,
Mar 23, 2015, 11:15:49 PM3/23/15
to python_in...@googlegroups.com
Thanks for the response. I don't think that will help me though. Maybe I don't understand what you mean.

In this case, I'm running a series of operations using third-party tool in Maya, and each operation takes 2-30 seconds to complete. The operations have to be run in Maya's main thread. After each operation, I can call QtCore.QCoreApplication.processEvents() and respond if my Cancel button was clicked, and that works. However, at the time the user actually clicks on the Cancel button, the GUI doesn't respond at all - ie the button doesn't depress, and I can't display a "cancelling..." type message. Because Maya and Qt are both running in the same thread, the first Qt knows of the click is after Maya returns from its operation.


On Tuesday, 24 March 2015 12:46:50 UTC+11, Justin Israel wrote:
If your goal is to keep your GUI reacting quickly, you can defer the call to the event loop. This will allow your button to fully click. Then the callback will run when control returns to Maya's event loop:

maya.utils.executeDeferred()

Ideally you are doing as much heavy lifting as you are able to to, in extra threads. But in the case where things must run in the main gui thread, your best bet is to defer them until after your gui can finish responding to the user interaction.

On Tue, Mar 24, 2015 at 1:57 PM Michael Boon <boon...@gmail.com> wrote:
Hi,

I have a few PySide tools that are multi-threaded and in general they work well. However, I can't figure out how to correctly make Maya do complex operations while keeping my Qt GUI responsive. Both systems insist on only being run from the main thread.

The Qt documentation says "The Qt GUI must run in this [the main] thread."
And the Maya documentation says "Maya commands throw an exception if they are called outside the main thread"

Is there a good way around this?

(Really all I want is to have a cancel button that will react immediately.)

Thanks,

Boon

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Justin Israel

unread,
Mar 23, 2015, 11:45:43 PM3/23/15
to python_in...@googlegroups.com
I see what you are referring to. 

The problem, as far as I know, is if the operation you are calling doesn't ever yield to the event loop at any point in its 2-30 seconds of processing, then all other events will queue up until control returns from that function. The pattern is actually similar to something in pure Qt, where you want to run something that takes time, in the main gui thread, but still allow it to be cancelled:

#pseudocode
for i in 1000:
    doSomething(i)
    if i % 10 == 0:
        qApp.processEvents()
        if checkCancelled():
            break

In something like that example, your long running operation would periodically yield to the event loop, and then check for user cancellation. That would allow for a cancel button to work during the time this is running in the main gui thread. But if your Maya operation never yields, then there isn't really anything you can do. 


To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/f5e38afa-5232-42cc-940e-a1f42d5e6477%40googlegroups.com.

Michael Boon

unread,
Mar 23, 2015, 11:48:05 PM3/23/15
to python_in...@googlegroups.com
Thanks. It's not what I wanted to hear, but it's good to know.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Marcus Ottosson

unread,
Mar 24, 2015, 3:31:04 AM3/24/15
to python_in...@googlegroups.com

There’s a few different ways of doing heavy processing in Maya, some might allow you to keep the UI responsive whilst others might not.

For example, if the heavy processing occurs between many frames, like a cache or playback of a heavy rig, then it looks like Qt does process events inbetween frames which would allow you to keep the UI moderately responsive - as in, not during a frame, but at least with similar lag to the viewport - and have you cancel-button do something like this.

for frame in cache_frames():
    if not isrunning:
        break

Where isrunning is toggled by your cancel button.

On the other hand, if the heavy processing takes place in pure Python, then you could safely thread it and allow Qt to process events in the main thread on it’s own, but I take it this isn’t your case.

Lastly, the heavy processing could occur within a single Maya command; like a long-running simulation or billion poly subdivision. In this case, it looks like you’re out of luck as Maya doesn’t seem to let Qt breathe until it’s completely finished. :(

IPC

For such a simple use-case, what I’m about to suggest is probably not worth it, but perhaps something to think about for your next project; a responsive UI is very important to the user experience, after all.

The above is just as you explained it; two event-loops fighting for attention. What you could do instead is put Qt in it’s own process and do communication via IPC. That way, they could both process events in their own main threads and regardless of how busy one gets, it will have no effect on the other.

The downside of course is having to manage IPC to begin with. RPC might give you the more similar experience of what it’s like without IPC and there are libraries out there to facilitate this such as Pyro, RPyC or PyRPC (by Justin, woh!).

Justin Israel

unread,
Mar 24, 2015, 3:38:35 AM3/24/15
to python_in...@googlegroups.com


My PyRPC works but was really more of an experiment I did when I first played with ZeroMQ.

If you are on linux, there is also dbus, which is a builtin message service so you can discover and communicate between apps. And also the basic command port if you just want a simple way to tell Maya to do stuff.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.

To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOAQzcePHpsgmvNGBgA4LAL8HDKzZWA5JFu707HpNo_%3Dsw%40mail.gmail.com.

Marcus Ottosson

unread,
Mar 24, 2015, 4:49:26 AM3/24/15
to python_in...@googlegroups.com
On second thought, if you've got a long-running Maya command, is it even possible to cancel?​ :O
Reply all
Reply to author
Forward
0 new messages