GObject.idle_add(),thread.join()和我的程序挂起 [英] GObject.idle_add(), thread.join() and my program hangs

查看:122
本文介绍了GObject.idle_add(),thread.join()和我的程序挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题:我的主线程应该启动并加入一个线程,该线程的运行时间约为10-15秒.

所以:

  • 我的主线程启动了一个子线程,该子线程必须运行大约10-15秒
  • 我的主线程加入了子线程:主线程需要子线程的结果
  • 在子线程运行的同时,我必须更新GUI ,它只是一个进度条(可能是每0.2秒)
  • 更新GUI:我将使用递归函数
  • 子线程完成,主线程获取结果
  • my main thread starts a child thread, whom has to run about 10-15 seconds
  • my main thread joins the child thread: the main thread needs the result of the child thread
  • in the meanwhile the child thread runs, i've to update the GUI, it is just a progressbar (possibly every 0.2 second)
  • updating the GUI: i'll use a recursive function
  • the child thread finishes and the main thread gets the result

我的代码存在的问题是 Trovarete_Window仅在worker函数已经结束时出现并开始更新 .因此,我的程序会挂起/冻结,直到工作程序运行为止.

The problem with my code is that the Trovarete_Window appears and starts to be updated only when the worker function has already ended. So my program hangs/freezes until the worker runs.

这是我的代码:

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

推荐答案

问题是您正在collegea_GUI内部调用t.join().调用t.join()意味着您的主线程-运行事件循环的线程-被阻塞,直到worker完成.只要您被阻塞在collegea_GUI中,您的主循环就无法运行,这意味着您计划的对pulse的调用将无法运行,并且GUI也无法更新.

The problem is that you're calling t.join() inside collegea_GUI. Calling t.join() means your main thread - the thread that's running the event loop - is blocked until worker completes. As long as you're blocked inside collegea_GUI, your main loop cannot run, which means the call to pulse you scheduled can't run, and the GUI can't be updated.

代替调用t.join(),您需要执行与pulse相似的操作-安排要运行的函数进行无阻塞检查,以查看worker是否完成.像这样:

Instead of calling t.join(), you'll need to do something similar to what you're doing with pulse - schedule a function to run that does a non-blocking check to see if worker is finished. Something like this:

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)

这篇关于GObject.idle_add(),thread.join()和我的程序挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆