我已閱讀,發佈/訂閱機制是從一個線程傳遞到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()
謝謝羅爾夫。它工作正常。太好了!我的理解是pub/sub機制本身並不是線程安全的。 CallAfter或CallLater是實際的線程安全均值。 –