GObject.idle_add(),thread.join()和我的程序挂起

时间:2014-10-03 01:36:29

标签: python multithreading gobject

我有一个问题:我的主线程应该启动并加入一个运行大约10-15秒的线程。

所以:

  • 我的主线程启动子线程,必须运行大约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

1 个答案:

答案 0 :(得分: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)