Question

J'ai un programme (temps maker lapse) qui a deux fils qui met à jour une wx.StaticBitmap. Lorsque les deux fils d'accéder au wx.StaticBitmap il se bloque avec l'erreur

python: xcb_io.c: 221: poll_for_event: Assertion `(((long) (Event_sequence) - (long) (demande dpy->)) <. = 0) » a échoué

J'ai essayé Google recherche pour la réponse et j'ai essayé de résoudre moi-même mais je ne peux toujours pas comprendre.

simple morceau de code qui reproduit cette erreur (ce n'est pas le programme réel) :

#!/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()

Je l'ai résolu avec wx.PostEvent Voir ma réponse.

Était-ce utile?

La solution 2

Je l'ai résolu avec 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()

Autres conseils

La meilleure façon d'éviter les accidents et le comportement anormal de toutes sortes est de faire en sorte que seules les principales poignées de fil de l'interface graphique. Vous pouvez essayer de le faire en trouvant et verrouillage des blocs de code critiques, mais à mon avis, c'est un jeu perdant. Beaucoup plus facile de synchroniser le fil de traitement (s) avec le fil conducteur à l'aide d'événements:

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>

dans la chaîne de traitement, et

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

dans le fil principal.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top