2017-10-21 5 views
0

を解決し---によりキャッチされない例外「NSRangeException」にクラッシュすると、wxPythonのGUIは、私はそのパブ/サブ機構を読んでいる

番組以下GUI(https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/)にスレッドから通信スレッドセーフ平均でありますより大きい1から問題の本質に縮小されているスレッドから、pub/subメカニズムを介してGUIのwx.TextCtrl領域へのいくつかの書き込み後にクラッシュします。いくつかの書き込みレートを試すには、time.sleep(x)ステートメントで変更することができます。どれがxであっても、それはクラッシュし(自分で0.1〜100秒の間にテストします)、スレッドがGUIに書き込む頻度ではありません。

基本的に、GUIはテキストコントロールを作成し、pub/subメカニズムにサブスクライブします。スレッドは定期的にパブリッシャに書き込みます。それは例外でクラッシュするまで正常に動作します:

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は実際のスレッドセーフな手段です。 –

関連する問題