【问题标题】:wxPython in MSYS2: SetLabel in threaded handler causes freeze?MSYS2 中的 wxPython:线程处理程序中的 SetLabel 导致冻结?
【发布时间】:2017-04-11 11:19:37
【问题描述】:

我正在 Windows 7、64 位、MSYS2 Mingw64 shell 上进行测试(shell 启动命令是C:\msys64\msys2_shell.cmd -use-full-path -mingw64);在这里,我通过pacmanmingw-w64-x86_64-python2-2.7.13-1mingw-w64-x86_64-wxWidgets-3.0.2-17mingw-w64-x86_64-wxPython-3.0.2.0-6 安装。

考虑这段代码,它只有标题标签、按钮和目标标签;单击按钮时,标签应从“X”变为“1”:

import wx #, wx.html
import sys, os
from threading import Thread

# disable buffering (Windows)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)

class Frame(wx.Frame):
  def __init__(self, *args, **kwds):
    kwds["style"] = wx.DEFAULT_FRAME_STYLE
    wx.Frame.__init__(self, *args, **kwds)

    self.label = wx.StaticText(self, wx.ID_ANY, "Click the button to change label below: ")
    self.bt_main = wx.Button(self, label="Click ME")
    self.bt_main.Bind(wx.EVT_BUTTON, self.BtnClickHandler)
    self.label2 = wx.StaticText(self, wx.ID_ANY, "XX")

    sizer_vmain_app = wx.BoxSizer(wx.VERTICAL)
    sizer_vmain_app.Add(self.label, proportion=0, flag=wx.EXPAND, border=0)
    sizer_vmain_app.Add(self.bt_main, proportion=0, flag=0, border=0)
    sizer_vmain_app.Add(self.label2, proportion=0, flag=0, border=0)

    self.SetSizer(sizer_vmain_app)
    self.Layout()

  def BtnClickHandler(self, event):
    testThread = Thread(target=self.DoBtnClick)
    testThread.start()
    testThread.join()

  def DoBtnClick(self):
    print("BtnClickHandler ")
    myval = int("1")
    self.label2.SetLabel(str(myval))

if __name__ == "__main__":
  app = wx.PySimpleApp(0)
  wx.InitAllImageHandlers()
  app_frame = Frame(None, wx.ID_ANY, "")
  app.SetTopWindow(app_frame)
  app_frame.Show()
  app.MainLoop()

当我按原样运行此代码时,应用程序会在遇到 self.label2.SetLabel(str(myval)) 时冻结。

但是,如果我避免使用线程,而是使用此函数:

  def BtnClickHandler(self, event):
    # testThread = Thread(target=self.DoBtnClick)
    # testThread.start()
    # testThread.join()
    self.DoBtnClick()

...然后一切正常。请注意,我通过在 MSYS2 Mingw64 shell 中运行 python test.py 来调用此脚本。

那么,是否可以在 Windows 上使用线程运行此代码,如果可以,如何? (否则,在 Linux 下使用线程运行它没有问题)

【问题讨论】:

  • 你看 wxpython 演示了吗?
  • 谢谢@Igor - 不,我没有,这有什么区别?这对我解决这个问题有什么帮助?
  • 对不起我的错。请在下面查看我的答案。

标签: windows multithreading wxpython wxwidgets msys2


【解决方案1】:

问题在于 wxWidgets 库不是线程安全的。

这意味着您无法从辅助线程访问 GUI 元素。仅从主线程(您在其上创建应用程序对象的线程)支持 GUI 访问。

【讨论】:

    【解决方案2】:

    您不能从除主线程之外的任何线程调用影响 GUI 的方法。相反,向主线程发布一个事件,要求它代表工作线程执行所需的操作。

    到目前为止,在 C++ 中,最简单的方法是将 CallAfter() 与 lambda 一起使用,例如你可以在线程代码中做CallAfter([=](){ label2->SetLabel(myval); })。不幸的是,我不知道这是否可以从 Python 获得。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-13
      • 2018-10-06
      • 2010-09-20
      • 2021-11-22
      • 2021-05-10
      • 2012-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多