由于未捕获的异常'NSRangeException'

时间:2017-10-21 16:04:49

标签: thread-safety wxpython

我已经读过pub / sub机制是从线程到GUI(https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/)进行通信的线程安全的意思

下面的程序,从较大的程序减少到问题的本质,在从线程到GUI的wx.TextCtrl区域通过pub / sub机制进行了多次写入后崩溃。为了试验几种写入速率,可以在time.sleep(x)语句中进行更改。无论x是什么,它崩溃(由我自己测试0.1到100秒),这不是线程写入GUI的频率问题。

基本上,GUI创建文本控件并订阅发布/订阅机制。该线程定期写入发布者。它可以正常工作,直到崩溃为止:

2017-10-21 13:50:26.221 Python[20665:d07] An uncaught exception was raised
2017-10-21 13:50:26.222 Python[20665:d07] NSMutableRLEArray insertObject:range:: Out of bounds
2017-10-21 13:50:26.222 Python[20665:d07] ([…])
2017-10-21 13:50:26.223 Python[20665:d07] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray 
insertObject:range:: Out of bounds'
*** First throw call stack:
([…]
)
libc++abi.dylib: terminating with uncaught exception of type NSException

'越界'可能与我无法从Python代码访问的索引有关...我无法继续下去。有人可以帮忙吗?

使用Python 2.7.12 | wxPython 3.0.2.0
正在运行Mac OS X 10.9.5 |在平台x86_64

代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__version__ = '04'

import sys
import threading
import time
import platform

try:
    import wx
except ImportError:
    raise ImportError ("The wxPython module is required to run this program")

try:
    from pubsub import pub
except ImportError:
    from wx.lib.pubsub import pub


class CrashFrame(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,parent,id,title)

        self.hor_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.textlogger = wx.TextCtrl(self, size=(520,110), style=wx.TE_MULTILINE | wx.VSCROLL, value="" )
        self.hor_sizer.Add(self.textlogger)
        self.SetSizerAndFit(self.hor_sizer)
        self.Show(True)

        self.crashthread = SocketClientThread()

        self.run()

    def run(self):
        self.logthistext('Using Python {} | wxPython {}'.format(sys.version.split()[0], wx.VERSION_STRING))
        self.logthistext('Is thread running ? - %s' % self.crashthread.isAlive())

        # Create a listener in the GUI form
        pub.subscribe(self.logthistext, 'fromSocketListener')

    def logthistext(self, msg):
        self.textlogger.AppendText('{}\n'.format(msg)) # a good way to write on the text area


class SocketClientThread(threading.Thread):
    def __init__(self):
        super(SocketClientThread, self).__init__()
        self.alive = threading.Event()
        self.alive.set()
        self.start() # thread will start at creation of the class instance

    def run(self):
        while self.alive.isSet():
            data = 'A bunch of bytes'
            pub.sendMessage('fromSocketListener', msg=data)
            time.sleep(10) # or 0.1 or 100, whatever, it crashes
            continue



if __name__ == '__main__':
    app = wx.App()
    frame = CrashFrame(None,-1,'Crash Program - v{}'.format(__version__))
    app.MainLoop()

1 个答案:

答案 0 :(得分:0)

wxPython的Threadsafe方法

wx.PostEvent
wx.CallAfter
wx.CallLater

drop table Current_Orders;
drop table Products;
drop table Customer;