wxpython创建循环的newevent会导致GUI放慢速度



我有一个线程运行,该线程可监视事物的状态,并发布一个事件,以最大速率为0.1s刷新GUI。但是,几个小时后,我注意到GUI变得迟钝并最终冻结。

class Hello(wx.Frame):
    def __init__(self):
        self.refreshEvent, EVT_REFRESH_GUI = wx.lib.newevent.NewEvent()
        self.Bind(EVT_REFRESH_GUI, self.__RefreshGui)
    def MyThread(self):
        while(True):
            # Do stuff
            self.var = self.GetVar()
            # Post refresh event.
            refreshEvent = self.refreshEvent()
            wx.PostEvent(self, refreshEvent)
            time.sleep(0.1)
    def __RefreshGui(self, event):
        pass

我只是意识到,如果我将refreshEvent = self.refreshEvent()移出段落循环外,一切似乎都更加响应。

我还没有看到有关创建引起滞后的新事件的任何信息。这是已知的和预期的行为吗?这是特别是由于wxpython,还是来自wxwidgets?

class Hello(wx.Frame):
    def __init__(self):
        self.refreshEvent, EVT_REFRESH_GUI = wx.lib.newevent.NewEvent()
        self.Bind(EVT_REFRESH_GUI, self.__RefreshGui)
    def MyThread(self):
        refreshEvent = self.refreshEvent()
        while(True):
            # Do stuff
            self.var = self.GetVar()
            # Post refresh event.
            wx.PostEvent(self, refreshEvent)
            time.sleep(0.1)
    def __RefreshGui(self, event):
        pass

编辑:

要解决当前的一些评论和答案,这是对实际代码的简化视图,以尝试关注导致我的问题的原因。是的,代码中有一个真实的线程。我们可以尝试为未来采用wxTimer方法,我感谢反馈,因为我想知道如何最好地解决这个问题。我们使用PostEvent的原因是因为我们需要它是安全的。以前,我们从不同的线程中遇到了segfault问题。有大量的遗产代码,当时这似乎是一种很好的方法。

这个问题真的想知道创建和发布的自定义事件数量是否存在固有的放缓。创建事件和发布事件的方法很多次都期望导致放缓吗?

仅仅因为您调用类方法MyThread并不能自动使其成为线程。但是在某种程度上,您已经在正确的轨道上。

您将需要在WXPYTHON WIKI上查看longRunningTasks,尤其是页面底部的"最简单的实现"部分最简单的实现 ever :(

您的GUI冻结,因为您正在通过无尽的while循环中的sleep饮食所有资源。这可以确保WXPYTHON将无法再对任何事件做出反应(也是您创建的事件(。

我的建议:首先,摆脱您的自定义活动。您在这里不需要。

您本质上有两个选择:

  1. sleep移动到单独的线程中,并以线程安全方式与主GUI线程进行通信(例如,wx.CallBack(。这在Wiki链接中很好地描述了。

  2. 如果您只需要每100 ms运行一次的代码,请使用wx.Timer(有关示例,请参见WXPYTHON演示(。但是,您必须确保,您的工作可以在100毫秒以下进行,否则活动将堆积起来。如果这是一个问题,请改用方法1。

而没有重复别人说的话,尽管我同意,这是一个简单的 wx.timer示例:

import wx
class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,size=(350, 225))
        panel = wx.Panel(self)
        self.Text = wx.StaticText(panel,-1,"Tick")
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.Text, 0, wx.ALL, 10)
        panel.SetSizer(sizer)
        self.timer.Start(2000) # fire every 2 seconds
        self.Show()
    def onTimer(self, evt):
        if self.Text.GetLabel() == "Tick":
            self.Text.SetLabel("Tock")
        else:
            self.Text.SetLabel("Tick")
if __name__ == '__main__':
    app = wx.App()
    MyFrame(None,"Tick Tock timer")
    app.MainLoop()

最新更新