2011-10-18 207 views
2

我有一個程序(時間間隔製造商)有兩個線程更新wx.StaticBitmap當兩個線程訪問wx.StaticBitmap它與誤差崩潰蟒蛇線程崩潰

蟒:xcb_io.c:221:poll_for_event:斷言`(((長) (event_sequence) - (長)(dpy->請求))< = 0)'失敗。

我試圖尋找答案一Google search,我試圖解決它自己,但我仍然無法弄清楚。

一段簡單的代碼再現此錯誤(這是不實際的程序)

#!/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解決它見我的答案。

回答

1

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() 
3

避免各種崩潰和異常行爲的最簡單方法是確保只有主線程處理GUI。您可以嘗試通過查找和鎖定關鍵代碼塊來實現,但在我看來這是一場失敗的遊戲。在主線程

while run: 
    self.timer_evt.wait()  # wait for main thread to unblock me 
    self.timer_evt.clear() 
    <process stuff, put results in queue or shared variables> 
在處理線程

,並

def tick(self): 
    if run: 
     <update GUI from queued data or shared variables> 
     self.timer_evt.set()   # unblock processing thread 
     self.root.after(ms, self.tick) # reschedule the GUI update 

:更容易使用的活動主線程處理線程(或多個)同步。

+0

我想你的答案,但不明白。 – linuxrules94

+0

更完整的示例會在處理線程中生成一些數據並將其顯示在主線程中。由於在你的例子中SetBitmap調用似乎是使用wx庫讀取圖像文件,所以沒有涉及任何單獨的「處理」。如果實際的程序做了一些處理來創建圖像(例如,從遠程服務器下載?),而不是從快速本地存儲讀取文件,那麼可以在單獨的線程中完成該處理。如果你只是在閱讀一堆文件,比如這個例子,問題是爲什麼要使用線程? – Dave