我已经读过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()
答案 0 :(得分:0)
wxPython的Threadsafe方法
wx.PostEvent
wx.CallAfter
wx.CallLater
drop table Current_Orders;
drop table Products;
drop table Customer;