python 线程崩溃
我有一个程序(延时制作器),它有两个更新 wx.StaticBitmap
的线程。 当两个线程访问wx.StaticBitmap
时,它会崩溃并出现错误
python: xcb_io.c:221: poll_for_event: 断言 `(((long) (event_sequence) - (long) (dpy->request)) <= 0)' 失败。
我尝试了Google 搜索寻找答案,我尝试自己解决它,但我仍然无法弄清楚。
一段简单的代码重现此错误 (这不是实际的程序):
#!/usr/bin/env python
import wx
import time,os.path,glob,threading
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.bitmap_1 = wx.StaticBitmap(self, -1, wx.NullBitmap)
self.__set_properties()
self.__do_layout()
wx.CallAfter(self._img)
def __set_properties(self):
self.SetTitle("frame_1")
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.bitmap_1, 0, 0, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
def _img(self):
Thread1= threading.Thread(target=self._img1)
Thread1.start()
Thread2 = threading.Thread(target=self._img2)
Thread2.start()
def _img1(self):
frames = glob.glob("/path/to/pngs/*.png")
frames.sort()
for i in range(len(frames)):
if os.path.isfile(frames[i]) and i%2 == 0:
print frames[i]
wx.Yield()
##time.sleep(0.5)
wx.CallAfter(self.bitmap_1.SetBitmap,wx.Bitmap(frames[i], wx.BITMAP_TYPE_ANY))
wx.CallAfter(self.Update)
def _img2(self):
frames = glob.glob("/path/to/pngs/*.png")
frames.sort()
for i in range(len(frames)):
if os.path.isfile(frames[i]) and i%2 == 1:
print frames[i]
wx.Yield()
##time.sleep(0.5)
wx.CallAfter(self.bitmap_1.SetBitmap,wx.Bitmap(frames[i], wx.BITMAP_TYPE_ANY))
wx.CallAfter(self.Update)
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
frame_1 = MyFrame(None, -1, "")
app.SetTopWindow(frame_1)
frame_1.Show()
app.MainLoop()
我用 wx.PostEvent
解决了它,请参阅我的答案。
I have a program (time lapse maker) which has two threads that updates a wx.StaticBitmap
. When the two threads access the wx.StaticBitmap
it crashes with the error
python: xcb_io.c:221: poll_for_event: Assertion `(((long)
(event_sequence) - (long) (dpy->request)) <= 0)' failed.
I tried a Google search for the answer and I tried to solve it myself but I still can't figure it out.
Simple piece of code that reproduces this error (this is not the actual program):
#!/usr/bin/env python
import wx
import time,os.path,glob,threading
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.bitmap_1 = wx.StaticBitmap(self, -1, wx.NullBitmap)
self.__set_properties()
self.__do_layout()
wx.CallAfter(self._img)
def __set_properties(self):
self.SetTitle("frame_1")
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.bitmap_1, 0, 0, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
def _img(self):
Thread1= threading.Thread(target=self._img1)
Thread1.start()
Thread2 = threading.Thread(target=self._img2)
Thread2.start()
def _img1(self):
frames = glob.glob("/path/to/pngs/*.png")
frames.sort()
for i in range(len(frames)):
if os.path.isfile(frames[i]) and i%2 == 0:
print frames[i]
wx.Yield()
##time.sleep(0.5)
wx.CallAfter(self.bitmap_1.SetBitmap,wx.Bitmap(frames[i], wx.BITMAP_TYPE_ANY))
wx.CallAfter(self.Update)
def _img2(self):
frames = glob.glob("/path/to/pngs/*.png")
frames.sort()
for i in range(len(frames)):
if os.path.isfile(frames[i]) and i%2 == 1:
print frames[i]
wx.Yield()
##time.sleep(0.5)
wx.CallAfter(self.bitmap_1.SetBitmap,wx.Bitmap(frames[i], wx.BITMAP_TYPE_ANY))
wx.CallAfter(self.Update)
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
frame_1 = MyFrame(None, -1, "")
app.SetTopWindow(frame_1)
frame_1.Show()
app.MainLoop()
I solved it with wx.PostEvent
See my answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(2)
我用wx.PostEvent解决了它:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Mon Oct 17 19:59:55 2011
import wx
import time,os.path,glob,threading
# begin wxGlade: extracode
# end wxGlade
ID_START = wx.NewId()
ID_STOP = wx.NewId()
# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()
def EVT_RESULT(win, func):
"""Define Result Event."""
win.Connect(-1, -1, EVT_RESULT_ID, func)
class ResultEvent(wx.PyEvent):
"""Simple event to carry arbitrary result data."""
def __init__(self, data):
"""Init Result Event."""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_RESULT_ID)
self.data = data
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.bitmap_1 = wx.StaticBitmap(self, -1, wx.NullBitmap)
self.__set_properties()
self.__do_layout()
# end wxGlade
self.frames = ""
EVT_RESULT(self,self.OnResult)
wx.CallAfter(self._img)
def __set_properties(self):
# begin wxGlade: MyFrame.__set_properties
self.SetTitle("frame_1")
# end wxGlade
def __do_layout(self):
# begin wxGlade: MyFrame.__do_layout
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.bitmap_1, 0, 0, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
# end wxGlade
def OnResult(self, event):
"""Show Result status."""
if event.data is None:
pass
else:
self.bitmap_1.SetBitmap(wx.Bitmap(event.data, wx.BITMAP_TYPE_ANY))
# end of class MyFrame
def _img(self):
Thread1= threading.Thread(target=self._img1)
Thread1.start()
Thread2 = threading.Thread(target=self._img2)
Thread2.start()
def _img1(self):
frames = glob.glob("/home/mitch/Pictures/*.png")
frames.sort()
for i in range(len(frames)):
if os.path.isfile(frames[i]) and i%2 == 0:
print frames[i]
##wx.Yield()
##time.sleep(0.5)
wx.PostEvent(self, ResultEvent(frames[i]))
def _img2(self):
frames = glob.glob("/home/mitch/Pictures/*.png")
frames.sort()
for i in range(len(frames)):
if os.path.isfile(frames[i]) and i%2 == 1:
print frames[i]
##wx.Yield()
##time.sleep(0.5)
wx.PostEvent(self, ResultEvent(frames[i]))
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
frame_1 = MyFrame(None, -1, "")
app.SetTopWindow(frame_1)
frame_1.Show()
app.MainLoop()
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
避免崩溃和各种异常行为的最简单方法是确保只有主线程处理 GUI。您可以尝试通过查找并锁定关键代码块来做到这一点,但在我看来,这是一场失败的游戏。使用事件将处理线程与主线程同步要容易得多:
在处理线程中和
在主线程中。
The easiest way to avoid crashes and anomalous behavior of all sorts is to ensure that only the main thread handles the GUI. You could try to do it by finding and locking critical code blocks, but in my opinion that's a losing game. Much easier to synchronize the processing thread(s) with the main thread using events:
in the processing thread, and
in the main thread.