首页 > 解决方案 > wxPython:只有主线程可以处理 Windows 消息错误

问题描述

当我第二次执行基于 wxpython 的 UI 时,我在下面发现了这个错误。UI 第一次启动和关闭时,它没有错误。但是,如果再次启动并关闭,则会出现一些错误,如下所示。我添加了一些调试日志以查看下面的线程名称。有谁知道这里有什么问题?一般来说,我想为主窗体创建新线程。

>>> import testui
>>> testui.run()
Launching TestUI thread...    
thread1 = MainThread
thread3 = Thread-11  
thread4 = Thread-11
thread2 = MainThread

>>> testui.run()
Launching TestUI thread...
thread1 = MainThread
thread3 = Thread-12
Exception in thread Thread-12:
Traceback (most recent call last):
File "c:\python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "c:\python27\lib\threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "c:\test\testui.py", line 587, in ui_thread_function
apps.MainLoop()
File "c:\python27\lib\site-packages\wx\core.py", line 2096, in MainLoop
rv = wx.PyApp.MainLoop(self)
wxAssertionError: C++ assertion "wxThread::IsMain()" failed at ..\..\src\msw\evtloop.cpp(182) in 
wxGUIEventLoop::Dispatch(): only the main thread can process Windows messages

thread2 = MainThread   

这是代码片段:

 import threading

 class MainFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        ...

    def OnClose(self, event):
        self.Destroy()

frmMainForm = None

class TestUIApp(wx.App):
    def OnInit(self):
        global frmMainForm
        frmMainForm = MainFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(frmMainForm)
        frmMainForm.Show()
        frmMainForm.Center()
        return True

def ui_thread_function():
    print("Launching Test UI thread...\n")
    apps = TestUIApp(0)
    main_thread = threading.currentThread()

    print("thread3 = %s" % main_thread.getName())
    apps.MainLoop()
    main_thread = threading.currentThread()
    print("thread4 = %s" % main_thread.getName())

def run():
    x = threading.Thread(target=ui_thread_function)
    x.start()
    main_thread = threading.currentThread()
    print("thread1 = %s\n" % main_thread.getName())
    x.join()
    main_thread = threading.currentThread()
    print("thread2 = %s" % main_thread.getName())

标签: pythonwxpython

解决方案


在 wx 框架中,不能为 GUI使用多个线程。有关如何使用wx.CallAfter异步将 GUI 更新从工作线程调度到主线程的更多信息,请参阅这两个链接:

在 python 中: 试图在另一个线程 wxpython 中创建一个对话框

在 C++ 中: https ://forums.wxwidgets.org/viewtopic.php?t=40332


推荐阅读