【问题标题】:Threading with WxPython event in MacOs在 MacOs 中使用 WxPython 事件进行线程化
【发布时间】:2016-06-03 22:52:22
【问题描述】:

我在 MacOs X 上使用 WxPython 并使用 pyCharm。我要做的是当我点击界面上的一个按钮时,它会生成一个新线程,然后这个新线程执行我的代码。

我明白了,但它崩溃了,我不知道为什么......

我得到的错误如下:

2016-02-22 14:13:36.641 Python[5694:698370] NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds
2016-02-22 14:13:36.643 Python[5694:698370] (
0   CoreFoundation                      0x00007fff91234ae2 __exceptionPreprocess + 178
1   libobjc.A.dylib                     0x00007fff977d973c objc_exception_throw + 48
2   CoreFoundation                      0x00007fff9123498d +[NSException raise:format:] + 205
3   Foundation                          0x00007fff9035bb32 -[NSMutableRLEArray replaceObjectsInRange:withObject:length:] + 156
4   UIFoundation                        0x00007fff919be488 -[NSLayoutManager removeTemporaryAttribute:forCharacterRange:] + 299
5   AppKit                              0x00007fff98a6a053 -[NSTextView _markForTextCheckingAfterChange] + 432
6   CoreFoundation                      0x00007fff911444ac __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
7   CoreFoundation                      0x00007fff91136165 __CFRunLoopDoBlocks + 341
8   CoreFoundation                      0x00007fff91135954 __CFRunLoopRun + 948
9   CoreFoundation                      0x00007fff91135338 CFRunLoopRunSpecific + 296
10  HIToolbox                           0x00007fff9fc27935 RunCurrentEventLoopInMode + 235
11  HIToolbox                           0x00007fff9fc2776f ReceiveNextEventCommon + 432
12  HIToolbox                           0x00007fff9fc275af _BlockUntilNextEventMatchingListInModeWithFilter + 71
13  AppKit                              0x00007fff988230ee _DPSNextEvent + 1067
14  AppKit                              0x00007fff98bef943 -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454
15  AppKit                              0x00007fff98818fc8 -[NSApplication run] + 682
16  libwx_osx_cocoau-3.0.0.2.0.dylib    0x0000000103d25418 _ZN14wxGUIEventLoop8OSXDoRunEv + 248
17  libwx_osx_cocoau-3.0.0.2.0.dylib    0x0000000103bf260f _ZN13wxCFEventLoop5DoRunEv + 31
18  libwx_osx_cocoau-3.0.0.2.0.dylib    0x0000000103b2b0e1 _ZN15wxEventLoopBase3RunEv + 65
19  libwx_osx_cocoau-3.0.0.2.0.dylib    0x0000000103af0787 _ZN16wxAppConsoleBase8MainLoopEv + 103
20  _core_.so                           0x00000001038033dc _ZN7wxPyApp8MainLoopEv + 76
21  _core_.so                           0x000000010384dd8f _wrap_PyApp_MainLoop + 79
22  Python                              0x00000001000c2d32 PyEval_EvalFrameEx + 20898
23  Python                              0x00000001000c4f93 PyEval_EvalCodeEx + 2115
24  Python                              0x000000010003e990 function_call + 176
25  Python                              0x000000010000cde2 PyObject_Call + 98
26  Python                              0x000000010001f43d instancemethod_call + 365
27  Python                              0x000000010000cde2 PyObject_Call + 98
28  Python                              0x00000001000c0c10 PyEval_EvalFrameEx + 12416
29  Python                              0x00000001000c3bcf PyEval_EvalFrameEx + 24639
30  Python                              0x00000001000c4f93 PyEval_EvalCodeEx + 2115
31  Python                              0x00000001000c50b6 PyEval_EvalCode + 54
32  Python                              0x00000001000e993e PyRun_FileExFlags + 174
33  Python                              0x00000001000e9bda PyRun_SimpleFileExFlags + 458
34  Python                              0x0000000100100bfd Py_Main + 3101
35  Python                              0x0000000100000f14 Python + 3860
36  ???                                 0x0000000000000002 0x0 + 2
)

但有时发生这种情况时,我会等待,并且代码正在同时执行...

当我再次执行此操作(单击按钮)时,它崩溃了...我认为这是因为我没有关闭线程,但我不知道是否需要这样做...

这是我用于创建线程的代码:

class CountingThread(threading.Thread):
    def __init__(self, parent):
        threading.Thread.__init__(self)
        self._parent = parent

    def run(self):
        """
        Overrided method.
        """
        self._parent.experiment_button()

这个事件函数调用这个类:

def OnButton(self, evt):
    worker = CountingThread(self)
    worker.start()

我不知道为什么会这样......

提前谢谢你!!!!

【问题讨论】:

  • 我看到的第一个问题是从线程回调到wxPython 不是线程安全的。永远不要直接从线程调用 GUI 的方法,因为 wxPython 不是这样设计的。但是,要线程安全地回调到wx,只需将方法包装在对wx.CallAfter 的调用中,如下所示:wx.CallAfter(self._parent.experiment_button)
  • @nepix32 我已经修改了它,并且知道我没有收到那个错误,但是它没有按我的需要工作,当我按下按钮时,代码正在执行,但是按钮仍然按下(似乎新线程不存在)......我想做的是在计算机处理算法时继续使用界面......

标签: python events wxpython


【解决方案1】:

似乎是LongRunningTask 的经典例子。请参阅最后一个示例,这是最容易实现的,但也请参阅其他可能性。

抱歉,我对您的情况不够具体:您必须将长时间运行的部分移到您的线程中。当experiment_button 事件触发时,分离线程并在线程完成期间/之后报告结果。

def run(self):
    """
    Overrided method.
    """
    # put long running part here
    # ... long running task
    # sprinkle with CallAfter as seen fit
    # ... continue task

    # signal the end result back thread-safely
    wx.CallAfter(self._parent.update_result, result)

【讨论】:

  • 我知道你在说什么,但我认为我必须改变我的代码结构......我有一个名为experiment_button的方法,它在一些算法之间执行。这个方法直到有结果才会结束,所以......我认为界面会冻结到那一刻......我不知道是否有解决这个问题的方法。如果没有,我认为我必须改变我的结构......非常感谢@nepix32
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
相关资源
最近更新 更多