Is updating a Control from another thread thread-safe?
#1
Currently I'm researching a possibility to update a xbmcgui Control from a background thread to display some live data in an addon window. So I've modified my second PyXBMCt example in the following way:

PHP Code:
import time
import threading
# Import PyXBMCt module.
import pyxbmct.addonwindow as pyxbmct


class MyWindow(pyxbmct.AddonDialogWindow):

    
def __init__(selftitle=''):
        
# You need to call base class' constructor.
        
super(MyWindowself).__init__(title)
        
# Set the window width, height and the grid resolution: 2 rows, 3 columns.
        
self.setGeometry(35015023)
        
# Create a text label.
        
self.label pyxbmct.Label(''alignment=pyxbmct.ALIGN_CENTER)
        
# Place the label on the window grid.
        
self.placeControl(self.label00columnspan=3)
        
# Create a button.
        
button pyxbmct.Button('Close')
        
# Place the button on the window grid.
        
self.placeControl(button11)
        
# Set initial focus on the button.
        
self.setFocus(button)
        
# Connect the button to a function.
        
self.connect(buttonself.close)
        
# Connect a key action to a function.
        
self.connect(pyxbmct.ACTION_NAV_BACKself.close)
        
update_thread threading.Thread(target=self.update_label)
        
update_thread.daemon True
        update_thread
.start()

    
def update_label(self):
        for 
i in range(11):
            
self.label.setLabel('Count: {0}'.format(i))
            
time.sleep(1.0)




# Create a window instance.
window MyWindow('Hello, World!')
# Show the created window.
window.doModal()
# Delete the window instance when it is no longer used.
del window 

Everything works as expected: the addon window pops-up and the label shows a live count from 0 to 10. But I wonder if this approach is thread-safe and does not pose any hidden dangers.
Reply
#2
Not thread safe would imply multiple threads accessing at the same time, but you only have one doing that here. So yes, it safe. The only possible 'hidden dangers' I can see (in this example it looks correct though) but once you start doing something less trivial, in my experience, daemon thread quickly gets messy and hard write correctly. It's usually always better to explicitly join() threads.

PS: 'del' does not 'delete the window instance'. It removes the name from the scope it was called, i.e in this case: nothing ;)
Reply
#3
(2014-12-12, 14:28)takoi Wrote: Not thread safe would imply multiple threads accessing at the same time, but you only have one doing that here. So yes, it safe.

Thanks for the explanation. The reason I've asked is that in some other other languages/GUI frameworks changing a widget status in a foreground thread from a background thread is usually forbidden by best practices. E.g. .NET WinForms widgets have a special Invoke() method to execute some code (including changing the state of the widgets themselves) in the thread they live. So I've had doubts if the same is true for xbmgcgui Controls.

Quote:PS: 'del' does not 'delete the window instance'. It removes the name from the scope it was called, i.e in this case: nothing Wink

I've got the impression that it's not that simple. Without del the following warning is written in the Kodi log:
Code:
14:40:31 T:4140 WARNING: CPythonInvoker(9, C:\Users\romanmi.LOGRUS-KYIV\AppData\Roaming\Kodi\addons\script.pyxbmct.demo\default.py): the python script "C:\Users\romanmi.LOGRUS-KYIV\AppData\Roaming\Kodi\addons\script.pyxbmct.demo\default.py" has left several classes in memory that we couldn't clean up. The classes include: class XBMCAddon::xbmcgui::ControlButton,class XBMCAddon::xbmcgui::ControlImage,class XBMCAddon::xbmcgui::ControlImage,class PythonBindings::XBMCAddon_xbmcgui_WindowDialog_Director,class XBMCAddon::xbmcgui::ControlButton,class XBMCAddon::xbmcgui::ControlLabel,class XBMCAddon::xbmcgui::ControlLabel
It's looks like Kodi does not call destructors for the instances of its C++ classes exposed to Python when exiting a Python script, which could potentially lead to memory leak. Please correct me if I'm wrong.
Reply
#4
(2014-12-12, 14:54)Roman_V_M Wrote:
(2014-12-12, 14:28)takoi Wrote: Not thread safe would imply multiple threads accessing at the same time, but you only have one doing that here. So yes, it safe.

Thanks for the explanation. The reason I've asked is that in some other other languages/GUI frameworks changing a widget status in a foreground thread from a background thread is usually forbidden by best practices. E.g. .NET WinForms widgets have a special Invoke() method to execute some code (including changing the state of the widgets themselves) in the thread they live. So I've had doubts if the same is true for xbmgcgui Controls.
I would guess they forbid it because it's virtual impossible to do threading right anyway. kodi doesn't forbid anything, so in that sense, I will have to change my answer to not safe. It shouldn't be too hard for you to induce a deadlock. (your example should still be fine as there is only one thread is accessing at the same) I don't know the entire api. I know there are some locking, but can't answer what is safe and what isn't sorry:\

(2014-12-12, 14:54)Roman_V_M Wrote: I've got the impression that it's not that simple. Without del the following warning is written in the Kodi log:
Code:
14:40:31 T:4140 WARNING: CPythonInvoker(9, C:\Users\romanmi.LOGRUS-KYIV\AppData\Roaming\Kodi\addons\script.pyxbmct.demo\default.py): the python script "C:\Users\romanmi.LOGRUS-KYIV\AppData\Roaming\Kodi\addons\script.pyxbmct.demo\default.py" has left several classes in memory that we couldn't clean up. The classes include: class XBMCAddon::xbmcgui::ControlButton,class XBMCAddon::xbmcgui::ControlImage,class XBMCAddon::xbmcgui::ControlImage,class PythonBindings::XBMCAddon_xbmcgui_WindowDialog_Director,class XBMCAddon::xbmcgui::ControlButton,class XBMCAddon::xbmcgui::ControlLabel,class XBMCAddon::xbmcgui::ControlLabel
It's looks like Kodi does not call destructors for the instances of its C++ classes exposed to Python when exiting a Python script, which could potentially lead to memory leak. Please correct me if I'm wrong.
Yeah, I have seen this with many addons. It happens when you create cyclic references for some reason. Haven't had the time to look into it, but it really shouldn't happen™.. I can only say: avoid creating cyclic references for the c++ classes in the first place, or break these references manually as you have. ("window = None" should do the same thoughWink) But nobody should be required to think about this when writing python code.
Reply

Logout Mark Read Team Forum Stats Members Help
Is updating a Control from another thread thread-safe?0