2013-08-28 42 views
0

我对wxpython的textctrl和线程有任何问题。希望在解决这个问题上有任何帮助。wxpython线程文本控件延迟

我的程序处理文件,当每个文件被处理时,它在文本控件中被列为完成。当只使用几个文件时,textctrl会自动响应并立即显示,并且不会消失。即使这些文件很大。对700mb文件和文本控件进行了测试,效果很好。

在许多文件上工作时出现问题,比如说20+。在这种情况下,textctrl会消失6或7秒,然后重新出现并正常工作。

我已经尝试了正常的线程,守护进程线程等。还尝试使用.join()这使事情变得更糟。我想知道这是否仅仅是因为我的程序是处理器密集型的,或者我只是做错了什么。

我的线程代码如下。到目前为止,这是迄今为止最快的方法,对我的目的来说还不够好。在此先感谢克林顿。

def Worker(self, e, _file): 

    match = '' 

    with open(_file, 'r') as f: 
     data = f.read() 

    for char in data: 
     if char in self.key: 
      match += chr(self.key.index(char)) 

    open(_file, 'w').close() 

    with open(_file, 'w') as f: 
     f.write(match) 

    wx.CallAfter(self.ListFilesEncrypt, e, _file) 

if __name__ == '__main__': 
    for _file in self.file2process: 
     self.filenum += 1 
     Thread(target=self.Worker, args=(e, _file,)).start() 
+0

你如何从线程更新文本控件?如果你直接调用文本控件,那么你有一个问题 –

+0

你是说你正在创建多个线程,可以一次更新文本控件? –

+0

说实话,不确定是python和编程的真正新手。上面的代码可以工作,但是当选择很多文件进行处理时,textctrl将消失6秒钟然后重新出现。一旦它重新出现,它就会像它应该做的那样工作。当每个文件都被处理后,它会被打印到文本控件中。所以textctrl输出与linux ls命令的输出类似。一旦开始印刷,它就可以正常工作,这只是令人烦恼的延迟。 –

回答

3

使用线程安全方法更新GUI。在wxPython中,有3个:

  • wx.CallAfter
  • wx.CallLater
  • wx.PostEvent

你也应该看看的wxPython的维基上的wxPython和线程信息:

我也写了关于这一主题的教程:

UPDATE:下面是创建40个线程和 “进程” 40个由文件的简单例子。它在每个线程完成时更新显示。但是,我没有看到您提到的问题。

import random 
import time 
import wx 

from threading import Thread 
from wx.lib.pubsub import Publisher 

######################################################################## 
class TestThread(Thread): 
    """Test Worker Thread Class.""" 

    #---------------------------------------------------------------------- 
    def __init__(self, fname, sleepAmt): 
     """Init Worker Thread Class.""" 
     Thread.__init__(self) 
     self.fname = fname 
     self.sleepAmt = sleepAmt 
     self.start() # start the thread 

    #---------------------------------------------------------------------- 
    def run(self): 
     """Run Worker Thread.""" 
     # This is the code executing in the new thread. 
     time.sleep(self.sleepAmt) 
     msg = "%s finished in %s seconds!" % (self.fname, self.sleepAmt) 
     wx.CallAfter(Publisher().sendMessage, "update", msg) 


######################################################################## 
class MyForm(wx.Frame): 

    #---------------------------------------------------------------------- 
    def __init__(self): 
     wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 

     panel = wx.Panel(self, wx.ID_ANY) 
     self.updateText = wx.TextCtrl(panel, style=wx.TE_MULTILINE) 
     self.btn = btn = wx.Button(panel, label="Start Thread") 

     btn.Bind(wx.EVT_BUTTON, self.onButton) 

     sizer = wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(self.updateText, 1, wx.ALL|wx.EXPAND, 5) 
     sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 
     panel.SetSizer(sizer) 

     # create a pubsub receiver 
     Publisher().subscribe(self.updateDisplay, "update") 

    #---------------------------------------------------------------------- 
    def onButton(self, event): 
     """ 
     Runs the thread 
     """ 
     for i in range(40): 
      fname = "test%s.txt" % i 
      secs = random.choice(range(3, 15)) 
      TestThread(fname, secs) 

    #---------------------------------------------------------------------- 
    def updateDisplay(self, msg): 
     """ 
     Receives data from thread and updates the display 
     """ 
     data = msg.data + "\n" 
     self.updateText.WriteText(data) 

#---------------------------------------------------------------------- 
# Run the program 
if __name__ == "__main__": 
    app = wx.PySimpleApp() 
    frame = MyForm().Show() 
    app.MainLoop() 

我在Windows 7上使用Python 2.6的wxPython 2.8.12.1

+0

感谢您的回复。应该提到我已经在使用ww.CallAfter。我甚至尝试将它们一起移除,以查看它的效果。即使不打印到textctrl,也不要回答以前的问题。它与选择处理的文件数量有关。克林顿。 –

+0

我编辑了问题并提供了工作线程函数的代码。 –

+0

感谢Mike的代码示例。原因你没有得到和我一样的问题很可能归结为你的代码与我的代码有些不同。我目前仍在研究第一个问题,目前大约有300行左右的代码,所以对我来说没有Hello World :-)我认为我将不得不再次重写(现在是5或6次)以你的代码为例。令我惊讶的是,与命令行程序相比,写一个GUI程序是多么困难。对我来说,它的代码量增加了一倍,复杂度增加了三倍。再次感谢克林顿。 –

0

你的线程应该更新文本控件直接 - 他们应该要么使用wx.CallAfter,或者更好的,设置的主要标志,(GIU),线程更新控制 - 这听起来像一个在线的方法可能是合适的。

+0

感谢您的回复。根据我对Mike Driscoll的回复的回复,我已经在使用wx.CallAfter,所以这不是问题。这与处理中选择的文件数量有关。即使删除wx.callafter,所以没有打印到textctrl。仍然有同样的问题。我会看看你的其他2条建议。克林顿。 –

0

比CPU密集型更多运行,也可以是IO密集型。 IO密集型应用程序可能会对性能产生非常大的影响,特别是当您将IO设备用于其他关键目的(如分页)时。我建议一次投5到10,然后排队。

+0

感谢您的回复。没有成功之前尝试排队一次,但会再试一次。我对编程还很陌生,所以可能会以某种方式搞砸了。 –