从wxPython Gui冻结OnDemand Python线程启动/连接

2024-10-01 15:34:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图构建一个非常简单的wxpythongui来监视和显示外部数据。有一个按钮可以打开/关闭监控。当监控打开时,GUI用实时数据更新两个wx静态标签。当监控关闭时,GUI将空闲。在

我试图用一个相当简单的Python线程布局来构建它。单击“开始监视”按钮时,程序将生成一个线程,该线程用实时信息更新标签。单击“停止监视”按钮时,螺纹连接()被调用,它应该停止。在

启动功能正常,实时数据更新也很好,但当我点击“停止”时,整个程序就冻结了。我在Windows7上运行这个64位,所以我得到了通常的“这个程序已经停止响应”窗口对话框。在

以下是相关代码:

class MonGUI(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        ...
        ... other code for the GUI here ...
        ...
        # Create the thread that will update the VFO information
        self.monThread = Thread(None, target=self.monThreadWork)
        self.monThread.daemon = True
        self.runThread = False

    def monThreadWork(self):
        while self.runThread:
            ...
            ... Update the StaticLabels with info
            ... (This part working)
            ...

    # Turn monitoring on/off when the button is pressed.
    def OnClick(self, event):
        if self.isMonitoring:
            self.button.SetLabel("Start Monitoring")
            self.isMonitoring = False
            self.runThread = False
            self.monThread.join()
        else:
            self.button.SetLabel("Stop Monitoring")
            self.isMonitoring = True

            # Start the monitor thread!
            self.runThread = True
            self.monThread.start()

我确信有更好的方法可以做到这一点,但我对GUI编程和Python线程还比较陌生,这是我想到的第一件事。在

那么,为什么点击按钮停止线程会让整个进程冻结?在


Tags: the数据self程序falsetruedefgui
3条回答

tom10的正确想法是避免从监视器线程更新UI。在

另外,在UI线程中使用阻塞调用self.monThread.join()可能不是一个好主意。如果您希望UI给出一些关于监视线程实际上已经结束的反馈,那么让monThreadWorker发出一个wx.CallAfter公司()或wx.事件后()就在它关闭之前。在

避免在UI线程中阻塞任何东西,这样可以避免UI死锁

在wxPython中,GUI操作需要在主线程中进行。在您的代码中,您正在从另一个线程调用GUI。在

最简单的解决方案是使用wx.CallAfter()。一行代码看起来像

wx.CallAfter(self.button.SetLabel, “Start Monitoring”)

然后会呼叫self.button.SetLabel函数完成后从主线程(“开始监视”)。在

还有其他方法可以解决这个问题,例如使用Python线程队列或wx.事件后,但从CallAfter开始,因为这是最简单的。在

其他问题也与此相关,比如不能重新启动同一个线程,但是使用CallAfter将停止崩溃。在

它很可能挂在^{}上,这会阻止调用线程,直到调用其join()方法的线程终止(正常情况下或通过未处理的异常)或直到出现可选超时。在

或者你的某个内部线程的某个调用从来没有阻塞过?当我编写一个获取COM端口数据的基本串行程序时,它有时会挂起,因为我线程中的一个read函数会阻塞,直到它得到一些东西。在

我将添加一些调试print语句来查看发生了什么。在

编辑:

我还将使用^{}而不是布尔标志,例如:

# in the init code...
self.runThread = threading.Event()

# when starting thread...
self.runThread.set()
self.monThread.start()

# in the thread...
while self.runThread.isSet():
    pass # do stuff

# killing the thread...
self.runThread.clear()
self.monThread.join()

这不应该让它的工作方式有所不同,但这是一种稍微安全的方法。在

相关问题 更多 >

    热门问题