2013-08-28 54 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

感謝您的回覆。沒有成功之前嘗試排隊一次,但會再試一次。我對編程還很陌生,所以可能會以某種方式搞砸了。 –