2017-10-21 413 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是實際的線程安全均值。 –

相關問題