Python GUI保持冻结状态,等待线程代码完成运行

时间:2016-03-26 00:47:19

标签: python multithreading

我有一个python GUI程序,需要执行相同的任务但有多个线程。问题是我调用线程,但它们不是并行执行,而是顺序执行。第一个执行,结束然后第二个,等等。我希望它们独立启动。

主要组成部分是:
 1.菜单(查看)
 2. ProcesStarter(控制器)
 3.流程(控制器)

菜单是您点击“开始”按钮的地方,该按钮调用 ProcesStarter 中的功能。

ProcesStarter 创建进程和线程的对象,并启动for循环中的所有线程。

菜单:

class VotingFrame(BaseFrame):

  def create_widgets(self):
    self.start_process = tk.Button(root, text="Start Process", command=lambda: self.start_process())
    self.start_process.grid(row=3,column=0, sticky=tk.W)

  def start_process(self):
    procesor = XProcesStarter()
    procesor_thread = Thread(target=procesor.start_process())
    procesor_thread.start()

ProcesStarter

class XProcesStarter:

   def start_process(self):
       print "starting new process..."

       # thread count
       thread_count = self.get_thread_count()

       # initialize Process objects with data, and start threads
       for i in range(thread_count):
          vote_process = XProcess(self.get_proxy_list(), self.get_url())
          t = Thread(target=vote_process.start_process())
          t.start()

过程:

class XProcess():

    def __init__(self, proxy_list, url, browser_show=False):
        # init code

    def start_process(self):
        # code for process

当我按下“启动过程”的GUI按钮时,gui被锁定,直到两个线程完成执行。 这个想法是线程应该在后台工作并且并行工作。

3 个答案:

答案 0 :(得分:3)

在将其指定为线程的目标时立即调用procesor.start_process()

#use this
procesor_thread = Thread(target=procesor.start_process)

#not this
procesor_thread = Thread(target=procesor.start_process())
                          # this is called right away ^

如果你马上调用它会返回None,这是Thread的有效目标(它什么都不做),这就是顺序发生的原因,线程没有做任何事情。

答案 1 :(得分:2)

将一个类用作线程的target的一种方法是使用该类作为目标,将构造函数的参数用作args

from threading import Thread
from time import sleep
from random import randint

class XProcesStarter:
  def __init__(self, thread_count):
    print ("starting new process...")
    self._i = 0
    for i in range(thread_count):
      t = Thread(
        target=XProcess,
        args=(self.get_proxy_list(), self.get_url())
      )
      t.start()


  def get_proxy_list(self):
    self._i += 1
    return "Proxy list #%s" % self._i

  def get_url(self):
    self._i += 1
    return "URL #%d" % self._i

class XProcess():    
  def __init__(self, proxy_list, url, browser_show=False):
    r = 0.001 * randint( 1, 5000)
    sleep(r)
    print (proxy_list)
    print (url)

def main():
  t = Thread( target=XProcesStarter, args=(4, ) )
  t.start()

if __name__ == '__main__':
  main()

此代码在python2和python3中运行。

原因是Thread对象的目标必须是可调用的(在python文档中搜索" callable"" __ call __"以获得完整的解释)。

编辑另一方面已在其他人的解答中得到解释(请参阅Tadhg McDonald-Jensen)。

答案 2 :(得分:2)

我认为您的问题是,在您开始线程的两个地方,您实际上都在调用要作为target传递给线程的方法。它在主线程中运行其代码(并尝试在返回值上启动新线程,如果有的话,一旦完成)。

尝试:

procesor_thread = Thread(target=procesor.start_process) # no () after start_process

t = Thread(target=vote_process.start_process) # no () here either