Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 带函数的线程和队列_Python_Multithreading_Lambda_Tkinter_Queue - Fatal编程技术网

Python 带函数的线程和队列

Python 带函数的线程和队列,python,multithreading,lambda,tkinter,queue,Python,Multithreading,Lambda,Tkinter,Queue,我在多线程和tkinter方面一直有困难slxl是我使用的一个模块,它可以工作,并且它的函数不返回值(只是为了确保没有混淆。) 以下是过去工作过的代码: #relevant tkinter code def create_widgets(): self.updatebttn = Button(self, text='Auto Update', command=self.spawnthread) self.updatebttn.grid(row=1

我在多线程和tkinter方面一直有困难
slxl
是我使用的一个模块,它可以工作,并且它的函数不返回值(只是为了确保没有混淆。)

以下是过去工作过的代码:

    #relevant tkinter code
    def create_widgets():

        self.updatebttn = Button(self, text='Auto Update', command=self.spawnthread)
        self.updatebttn.grid(row=1, column=0, sticky=N)

        self.progressbar = Progressbar(self, orient='horizontal',
                                       length=300, mode='determinate')
        self.progressbar.grid(row=1, column=1, sticky=W)
        self.progressbar["maximum"] = (slxl.sizeFinder()) * 1.1


    def spawnthread(self):
        self.updatebttn.config(state="disabled")
        self.thread = ThreadedClient1(self.queue)
        self.thread.start()
        self.periodiccall()

    def periodiccall(self):
        if self.thread.is_alive():
            self.after(100, self.periodiccall)
            self.progressbar.step(500)
        else:
            self.updatebttn.config(state="active")
            self.progressbar.stop()

class ThreadedClient1(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue
    def run(self):
        time.sleep(1)
        importer = slxl.runImportAndCoordAdder()
        self.queue.put(importer)
问题是,我希望ThreadedClient1能够将它放入队列的函数作为参数,在本例中,
slxl.runImportAndCoordAdder()
,因为我对不同的函数多次使用
ThreadedClient
(我以后在程序中对它的使用相同,只是使用了不同的函数)我不喜欢使用
ThreadedClient1
ThreadedClient2
,唯一的区别是
importer=
不同的功能

我确实尝试过使用lambda这样的解决方案:

def spawnthread(self):
    self.updatebttn.config(state="disabled")
    self.thread = ThreadedClient1(self.queue, lambda: slxl.runImportAndCoordAdder())
    self.thread.start()
    self.periodiccall()

#periodic call is the same

class ThreadedClient1(threading.Thread):
    def __init__(self, queue, fcn):
        threading.Thread.__init__(self)
        self.queue = queue
        self.fcn = fcn
    def run(self):
        time.sleep(1)
        self.queue.put(lambda: self.fcn)
这不起作用,因为它忽略了我感兴趣的功能,将progressbar稍微移动/禁用,并启用了按钮,然后结束

我做错了什么

编辑: 问题解决了。然而,另一个问题出现了。我想将
spawnthread
periodiccall
ThreadedClient
转移到我拥有的小部件模板模块中,并对它们进行概括,以便轻松使用。我这样做:

def spawnthread(self, widget):
    widget.config(state="disabled")
    self.thread = ThreadedClient1(self.queue)
    self.thread.start()
    self.periodiccall()
这很有效,直到我尝试推广
periodiccall

    #...
        self.periodiccall(widget=widget)

    def periodiccall(self, widget=None):
        if self.thread.is_alive():
            self.after(100, self.periodiccall)
            self.progressbar.step(500)
            #print widget
        else:
            widget.config(state="active")
            self.progressbar.stop()

我打开了
打印小部件
,查看发生了什么,因为我一直得到一个属性错误。似乎正在发生的是,它第一次运行函数时知道“widget”是什么,然后在
None
语句中调用
self.periodiccall
将其转换为
after
语句中的
self.periodiccall
。至少,我认为这是正在发生的事情。如何删除此错误并使小部件成为此递归函数中的变量

问题在于,将函数用作
ThreadedClient1
的参数时,没有调用该函数:

class ThreadedClient1(threading.Thread):
    # ...
    def run(self):
        time.sleep(1)
        self.queue.put(lambda: self.fcn)
它只是一个函数,返回对作为参数传递的lambda的引用,而不是调用
slxl.runImportAndCoordAdder()
的结果。应该是:

class ThreadedClient1(threading.Thread):
    # ...
    def run(self):
        time.sleep(1)
        self.queue.put(self.fcn())
或直接引用的其他解决方案(不含lambdas):


完美的这正是我需要的。我使用lambdas是因为我希望能够将spawnthread、periodicall和threadedclient转储到我的小部件模板模块中,以保证代码的整洁;我把它加到原来的问题上。
def spawnthread(self):
    self.updatebttn.config(state="disabled")
    self.thread = ThreadedClient1(self.queue, slxl.runImportAndCoordAdder)
    self.thread.start()
    self.periodiccall()

class ThreadedClient1(threading.Thread):
    # ...
    def run(self):
        time.sleep(1)
        self.queue.put(self.fcn())