是否有某种类型的打印缓冲区溢出,当WriteText (AppendText, SetLabel等)连续在wxPytho



我有一些文本在输出中有点连续(在实际应用程序中大约每两秒钟出现一次)。

print进入终端时,无论我保持运行循环多长时间,一切都很好。

然而,当引导打印到wx帧时,打印动作本身进行得很好,这里没有问题,但是如果我保持运行循环超过10-20个周期,我不再能够正常关闭窗口(在这个例子中鼠标或Ctrl+F4,但如果我构造一个显式的退出事件菜单也是一样的)。线程中的动作停止了,但是应用程序挂起了——它只能由操作系统(在我的情况下是Windows)用"强制关闭/等待程序响应"对话框关闭。但是,当终端窗口处于焦点时,可以使用Ctrl+C立即关闭它。看起来好像有什么东西填满了太多的文本并锁定了关闭进程。

在多行wxTextCtrl窗口上与WriteTextAppendText一起发生,或者与下面测试代码中的SetLabel一起发生。

在这个测试中,如果我在启动后几乎立即关闭wx窗口,它关闭得很好。如果我继续运行循环更长时间(或者注释掉两个time.sleep()行),那么无论何时尝试关闭窗口,挂起都会成功。

我在这里错过了什么?(有什么东西要冲吗?)

edit嗯,这个问题可能与"线程安全方法"有关,正如这里简要描述的那样。我会在那个方向做一些测试,必须找出wx.CallAfter, wx.CallLaterwx.PostEvent的正确用法。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wx
import time
import threading
class TestFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.sometext = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY)
        self.thread = None
        self.alive = threading.Event()
        self.__set_properties()
        self.__do_layout()
        self.__attach_events()
        self.StartThread()
    def __set_properties(self):
        self.SetTitle("test")
    def __do_layout(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.sometext, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()
    def __attach_events(self):
        self.Bind(wx.EVT_CLOSE, self.OnClose)
    def OnClose(self, event):
        """ stop & close on system window close """
        self.StopThread()
        self.Destroy()
    def StartThread(self):
        """ start the thread """
        self.thread = threading.Thread(target=self.TestThread)
        self.thread.setDaemon(1)
        self.alive.set()
        self.thread.start()
    def StopThread(self):
        """ stop the thread, wait util it is finished """
        if self.thread is not None:
            self.alive.clear()
            self.thread.join()
            self.thread = None
    def TestThread(self):
        """ main thread """
        while self.alive.isSet():
            self.sometext.SetLabel("Hello")
            time.sleep(0.5)
            self.sometext.SetLabel("Python")
            time.sleep(0.5)
class MyApp(wx.App):
    def OnInit(self):
        wx.InitAllImageHandlers()
        frame = TestFrame(None, -1, "")
        self.SetTopWindow(frame)
        frame.Show(1)
        return 1
if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

我已经用AppendtText改变了每个SetLabal。我不知道为什么,但是SetLabel函数不能正确地为我工作。

几秒钟后,应用程序将停止工作。这是我的错误输出:

(python:14099): Pango-CRITICAL **: pango_layout_get_iter: assertion 'PANGO_IS_LAYOUT (layout)' failed
Segmentation fault

之后,我使用CallAfter函数http://wiki.wxpython.org/CallAfter应用程序开始为我正确工作。我的TestThread版本:

def TestThread(self):
        """ main thread """
        while self.alive.isSet():
            wx.CallAfter(self.sometext.AppendText, "Hello")
            time.sleep(0.5)
        wx.CallAfter(self.sometext.AppendText, "Python") 
        time.sleep(0.5)
        wx.CallAfter(self.sometext.Clear)

我希望这对你有帮助。