robotools / vanilla

A Pythonic wrapper around Cocoa.
MIT License
78 stars 28 forks source link

Thread safety #61

Closed schriftgestalt closed 10 months ago

schriftgestalt commented 6 years ago

Is there interest in making vanilla a bit more thread save? For example currently it is dangerous to change the content of a TextBox from a background thread. It could be handled like this:

        if NSThread.isMainThread():
            if isinstance(value, NSAttributedString):
                self._nsObject.setAttributedStringValue_(value)
            else:
                self._nsObject.setStringValue_(value)
        else:
            if isinstance(value, NSAttributedString):
                self._nsObject.performSelectorOnMainThread_withObject_waitUntilDone_("setAttributedStringValue:", value, False)
            else:
                self._nsObject.performSelectorOnMainThread_withObject_waitUntilDone_("setStringValue:", value, False)

It is not pretty but works. I couldn’t find a python version.

justvanrossum commented 6 years ago

The objc module has a convenience function called callAfter(func, *args, **kwargs), which calls performSelectorOnMainThread_withObject_waitUntilDone, so that makes it a lot easier.

I think it's the responsibility of the caller to make sure such calls are done on the main thread, and not vanilla's, just like it is with Cocoa itself.

schriftgestalt commented 6 years ago

But that has to be documented. And how do I call a python method on the foreground? Most public vanilla classes are not NSObject and thus don’t respond to performSelectorOnMainThread_withObject_waitUntilDone.

schriftgestalt commented 6 years ago

I couldn’t find callAfter in the objcmodule but this works:

from PyObjCTools import AppHelper
AppHelper.callAfter(self.progressWindow.close, None)
justvanrossum commented 6 years ago

Sorry, that's indeed the correct module. I use from PyObjCTools.AppHelper import callAfter.

callAfter() also works for Python methods on non-NSObject instances. Any Python callable.

Documentation: don't assume anything is ever thread-safe unless it's documented to be thread-safe :)

schriftgestalt commented 6 years ago

I know about the thread safety, but I fear a lot scripter don’t.

justvanrossum commented 6 years ago

If you run a thread you better understand about thread safety.

But let me guess: If a host app runs user scripts from a thread, well, I don't know, but it could be in for a lot of trouble.

But ok, let's see, what would it take to make vanilla thread-safe enough for such usage? Doing TextBox().set() is one thing, but to do that everywhere may be a lot of changes that are hard to test.