WxPython在循环中创建NewEvent会导致GUI速度减慢

WxPython在循环中创建NewEvent会导致GUI速度减慢,wxpython,wxwidgets,Wxpython,Wxwidgets,我有一个线程正在运行,它监视事物的状态,并发布一个事件来刷新Gui,最大速率为0.1秒。然而,几个小时后,我注意到Gui变得迟钝,最终会冻结 class Hello(wx.Frame): def __init__(self): self.refreshEvent, EVT_REFRESH_GUI = wx.lib.newevent.NewEvent() self.Bind(EVT_REFRESH_GUI, self.__RefreshGui)

我有一个线程正在运行,它监视事物的状态,并发布一个事件来刷新Gui,最大速率为0.1秒。然而,几个小时后,我注意到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()
移动到while循环之外,一切看起来都会更加灵敏

我没有看到任何关于创建导致延迟的新事件的内容。这是已知的和预期的行为吗?这是因为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
并不会自动使其成为线程。但在某种程度上,你已经走上了正确的轨道

您需要查看主题,尤其是页面底部的最简单的实现:)部分

您的GUI冻结,因为您在无休止的
while
循环中通过
sleep
ing耗尽了所有资源。这保证了wxPython将不再能够对任何事件(也是您自己创建的事件)做出反应

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

您基本上有两种选择:

  • sleep
    移动到一个单独的线程中,并以线程安全的方式(例如
    wx.CallBack
    )与主GUI线程通信。这在wiki链接中有很好的描述

  • 如果您只需要一些每100毫秒运行一次的代码,请使用
    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()
    

    我不是Python程序员,但对我来说它不像线程,为什么不使用
    wxTimer
    ,你可以把它放在
    Hello
    类的构造函数中。在实际情况中,
    MyThread
    是一个真正的线程,我只是试图将代码简化为导致问题的原因。也许这是个错误。我不使用
    wxTimer
    的原因是,出于遗留代码的原因,它需要是线程安全的。可以从其他线程调用东西并导致错误。是的,也许我们可以迁移到这一点,但问题是,试图在无限循环中创建和使用“PostEvent”是否存在固有的问题。在实际情况中,MyThread实际上是一个真正的线程,而不仅仅是一个线程。在真实的情况下,我们并没有以这种确切的方式使用sleep,但从我所知道的情况来看,sleep确实释放了pythongil。几小时后出现迟滞,约8小时后出现冻结。我们正在做一个“PostEvent”,因为我们需要一种线程安全的方式来调用我们的函数(一些遗留代码问题,但是是的,我们可以尝试移动到
    wx.Timer
    )。我想我还不够清楚,但我想知道的是,在无限循环中创建和发布事件是否会导致最终冻结。