Hello all,
I am working on adding threading for updating data aside from the UI in an application I am making.
Under “6. Notes about this example” on this page: https://wiki.wxpython.org/Non-Blocking%20Gui, it says that:
Using events to pass back data will work well in most cases but if you have a or many worker threads that send results at a very rapid rate and in high volume there are better solutions to improve performance and reduce overhead. As handling the high volume of events can once again lead to blocking on the main thread. These other approaches are also not very difficult, I may add a supplemental example at some time if there is interest.
I am wondering how to implement this for high volume of events?
EDIT: Right now I am using wx.PostEvent but the program seems to crash when the worker thread can’t keep up with the events.
It seems that it would be best to stop the data processing in the background halfway through the thread working if there is another event rather than continuing to process before handling the latest event (similar to “bounce” for data entered into an input calling to a web API) but I am not sure how to implement this with wxPython, or if this is the best way to handle this.
Below is what I am doing now:
Thread.py
from threading import *
import wx
# Define notification event for thread completion
EVT_RESULT_ID = wx.NewIdRef()
def EVT_RENDER_RESULT(win, func):
""" Define result event """
win.Connect(-1, -1, EVT_RESULT_ID, func)
class ResultEvent(wx.PyEvent):
""" Simple event to carry arbitrary result data """
def __init__(self, data):
"""Init Result Event."""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_RESULT_ID)
self.data = data
class RenderThread(Thread):
""" Thread class that executes processing """
def __init__(self, parent):
""" Init the worker thread"""
Thread.__init__(self)
self._parent = parent
# Starts the thread running
self.start()
def run(self):
""" Run the worker thread """
# Code executing in the new thread here. My actually code here is compositing images with Pillow, etc.
render_image = # do my stuff here
# The result returned
wx.PostEvent(self._parent, ResultEvent(render_image))
Main application code:
class MainApplication(wx.Frame):
def __init__(self, arguments):
wx.Frame.__init__(self, None, title="", size=(1000, 800))
# Indicate we don't have a worker thread yet
self.worker = None
# Set up event handler for worker thread results
EVT_RENDER_RESULT(self, self.OnResult)
...
def OnResult(self, event):
# Update my stuff here and get the result...
# The worker thread is done
self.worker = None
def Render(self):
""" This is the method that is actually called when something is updated
"""
# Update stuff....
self.worker = RenderThread(self) # From thread.py
When render
is called too much in a short period of time, the program seems to crash.
Any help is greatly appreciated.
Thank you.