2017-10-21 271 views
0

我已阅读,发布/订阅机制是从一个线程传递到GUI(https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/)以下wxPython的GUI崩溃因未捕获的异常“NSRangeException” ---解决

程序的线程安全的意思,它已经从一个更大的问题的实质减少,从线到wx.TextCtrl区域通过发布/订阅机制的GUI的一些著作后崩溃。为了试验几个写入率,可以在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() 

回答

0

wxPython中的线程安全的方法

wx.PostEvent
wx.CallAfter
wx.CallLater

def run(self): 
    x=0 
    while self.alive.isSet(): 
     data = 'A bunch of bytes-'+str(x) 
     wx.CallAfter(pub.sendMessage,'fromSocketListener', msg=data) 
     time.sleep(0.2) # or 0.1 or 100, whatever, it crashes 
     x +=1 
+0

谢谢罗尔夫。它工作正常。太好了!我的理解是pub/sub机制本身并不是线程安全的。 CallAfter或CallLater是实际的线程安全均值。 –

相关问题