RV and Python Threading - Best practices?

Hi all, I am currently working on an extension for RV that involves downloading version URLs from Shotgun and loading them into the current session that is piggy-backing on SG Review. One of the things we want to be able to do is download the URLs in the background.I have tried doing this with python’s threading module, but am seeing intermittent crashing that I suspect occurs when trying to call rv.commands.setSourceMedia from the thread. It is my understanding that RV Commands are not thread safe per this post from the old community forums: https://support.shotgunsoftware.com/hc/en-us/community/posts/210122908-Running-python-thread-from-rv-menu

Is there a proper way to send information to RV that would allow me to call RV Commands from the main thread when the work is done without locking out my user? Is the network protocol workaround mentioned in that post still the recommended way to handle it? CC’ing @nico.vandenbosch

Thanks,

JD Arredondo

3 Likes

Interesting problem. I have absolutely no experience of this so apologies if this is a daft suggestion, but could you subprocess rvpush to push media in to your current session? Feels like a nasty hack to get things done though.

1 Like

Hi JD,

This is correct, you should limit your access to RV’s API through the main thread. Qt practices by default Thread Affinity through objects. See this: https://doc.qt.io/qt-5/qobject.html#thread-affinity

To do this properly, you should create an object on the main thread that has a Qt Slot that you can connect to a QObject in your worker thread. By emitting the signal, the Qt event loop will ensure that the slot is called on the thread in which the target object was created. This also keeps RV working within the existing event loop so it doesn’t step on other timing as best as it can.

The network protocol is probably not nearly as clean as just using Qt signals to do that.

Cheers,
-Kessler

1 Like

As a more direct example, check out how Toolkit handles this. You’ll see that when a job is scheduled, it registers signals to be able to communicate back to the world.

Keeping track of object thread ownership is important even in PySide apps, as any C++ component (such as a compiled portion of a library) needs to be run in the appropriate thread to avoid thread issues. RV has a lot of time-dependent work going on, so it can be pretty obvious when you step on threads in RV.

1 Like