2014-10-03 27 views
0

我有一個問題:我的主線程應該啓動並加入一個線程,該線程運行約10-15秒。GObject.idle_add(),thread.join()和我的程序掛起

所以:

  • 主線程啓動子線程,其中具有運行約10-15秒
  • 主線程加入子線程:主線程需要結果的子線程
  • 同時子線程運行,我要更新GUI,它只是一個進度條(可能每0.2秒)
  • 更新GUI:我會用一個遞歸函數
  • 子線程結束,主線程得到結果

我的代碼的問題是,Trovarete_Window出現並開始僅當工作人員功能已結束時才更新。所以我的程序掛起/凍結,直到工人運行。

這裏是我的代碼:

def collega_GUI(widget, args=()): 

    builder.get_object('Trovarete_Window').show_all() 
    progressbar.set_pulse_step(0.20) 

    pulse() 
    t = threading.Thread(target=worker) 
    t.setDaemon(True) 
    t.start() 
    t.join() 
    print 'a' 


def pulse(): 

    if not event.is_set(): 
     progressbar.pulse() 
     GObject.timeout_add(300, pulse) 


def worker(): 
    #hard work 
+0

'collega_GUI'叫什麼?主循環在哪裏開始? – dano 2014-10-03 01:38:59

+0

另外,你需要從'worker',它需要主線程阻塞,直到它完成?你真正的程序如何真正從工作者線程獲得結果? – dano 2014-10-03 01:42:56

+0

1)從Gtk.Button調用collega_gui。 2)當子線程結束時,它會設置一個結果變量。該變量由函數返回,在join()之後調用。 – FrancescoN 2014-10-03 01:49:26

回答

1

的問題是,你打電話t.join()collegea_GUI。調用t.join()意味着您的主線程 - 運行事件循環的線程 - 將被阻止,直到worker完成。只要您在collegea_GUI內被阻止,您的主循環就無法運行,這意味着您調度的pulse無法運行,並且無法更新GUI。

與其說t.join()的,你需要做類似的東西你與pulse做什麼 - 安排一個函數來運行,它看到了非阻塞檢查,如果worker完成。像這樣:

def collega_GUI(widget, args=()): 

    builder.get_object('Trovarete_Window').show_all() 
    progressbar.set_pulse_step(0.20) 

    pulse() 
    t = threading.Thread(target=worker) 
    t.setDaemon(True) 
    t.start() 
    wait_for_t(t) 

def wait_for_t(t): 
    if not t.is_alive(): 
     t.join() # This won't block, since the thread isn't alive anymore 
     print 'a' 
     # Do whatever else you would do when join() (or maybe collega_GUI?) returns 
    else: 
     Gobject.timeout_add(200, wait_for_t, t) 
+0

沒關係,謝謝你的回覆,但有一個問題:我不能把其餘的代碼放在wait_for_t裏面。 collega_GUI是我的主線程,它具有所有的數據結構。我會盡力回答,雖然我還有一個小問題(我認爲) – FrancescoN 2014-10-03 02:50:13

+0

更新:我沒有找到另一種方式 – FrancescoN 2014-10-04 23:32:25