Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.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
后台进程锁定GUI Python_Python_Python 2.7_Multiprocessing - Fatal编程技术网

后台进程锁定GUI Python

后台进程锁定GUI Python,python,python-2.7,multiprocessing,Python,Python 2.7,Multiprocessing,我有一个后台进程(使用多处理中的进程)将对象推送到我的GUI,但是这个后台进程一直锁定GUI,并且推送的更改永远不会显示。对象被放入我的队列,但是我的GUI中的更新方法没有被定期调用。我可以做些什么使GUI更新更定期?我的GUI是用Tkinter编写的 我的后台进程中有一个无限循环,因为我总是需要不断读取USB端口以获取更多数据,所以我的代码基本上如下所示: TracerAccess.py ui.py Main.py 因此后台线程永远不会结束,但是当我结束进程时,UI在关闭之前开始显示。这个问题

我有一个后台
进程
(使用
多处理
中的
进程
)将对象推送到我的GUI,但是这个后台进程一直锁定GUI,并且推送的更改永远不会显示。对象被放入我的队列,但是我的GUI中的更新方法没有被定期调用。我可以做些什么使GUI更新更定期?我的GUI是用Tkinter编写的

我的后台进程中有一个无限循环,因为我总是需要不断读取USB端口以获取更多数据,所以我的代码基本上如下所示:

TracerAccess.py ui.py Main.py
因此后台线程永远不会结束,但是当我结束进程时,UI在关闭之前开始显示。这个问题可能是因为我设计了TracerAccess.py模块,因为我是在移动了直接形式的java之后开发这个模块的,并且几乎没有python的设计经验

在内部,
multiprocess.Process
所做的实际上是一个复制过程,它有效地复制了您的过程。您或许可以将其想象为:

                  / ["background" process] -------------\
[main process] --+                                       +-- [main process]
                  \ [main process continued] -----------/
p.join()
尝试将两个进程“连接”回一个进程。这实际上意味着:等待后台进程完成。以下是
.join()
函数中的实际(完整)代码:

def join(self, timeout=None):
    '''
    Wait until child process terminates
    '''
    assert self._parent_pid == os.getpid(), 'can only join a child process'
    assert self._popen is not None, 'can only join a started process'
    res = self._popen.wait(timeout)
    if res is not None:
        _current_process._children.discard(self)
注意如何调用
self.\u popen.wait

这显然不是你想要的

在TKinter的上下文中,您可能希望使用tk事件循环,例如(Python3,但该概念也适用于Python2)

您不调用
.join()
,而是使用
.after()
方法,该方法将函数调度为在
n
微秒后运行(如果您使用过Javascript,则考虑
setTimeout()
)来读取队列

根据
bg()
函数的实际内容,您可能根本不需要执行
多过程,只需使用
.after()
调度函数就足够了

另见:

您使用
多处理的基本思想是好的,但可能您使用错了?(例如,立即调用
.join()
)。您应该发布代码,最好是@ru毯冒烟者。我已经添加了一个关于该问题和无限循环的类似示例。
self.checkqueue()
不能阻止(长时间):使用
q.get\u nowait()
而不是
q.get()
。下面是我使用了您非常好的示例,并在使用
.after()
时添加了更多详细信息,但我的后台进程正在执行一些密集操作,然后在执行密集操作时遇到了困难,after方法将不再被调用。@Dean我已更新示例代码以包含更多输出,它现在在队列上使用
get_nowait()
,因此不会阻塞。除此之外,这似乎对我来说效果相当不错……我已经能够用一个较小的示例来复制我的问题,并且我已经更新了问题中的源代码。@Dean一个明显的问题:在
ui.py
Application.startTrace
中,您可以:
self.splitProc=Process(target=self.dataAbstraction.readInput())
,您当然不希望括号出现,这会导致函数立即执行,而不是被设置为
目标(现在返回值被设置为目标,但由于此函数是一个永无止境的
,而True
循环,因此脚本会冻结)。现在目标函数不会执行。这可能就是它存在的原因。
import ui as ui

if __name__ == "__main__":
    root = Tk()
    root.columnconfigure(0,weight=1)
    app = ui.Application(root)
    app.mainloop()
                  / ["background" process] -------------\
[main process] --+                                       +-- [main process]
                  \ [main process continued] -----------/
def join(self, timeout=None):
    '''
    Wait until child process terminates
    '''
    assert self._parent_pid == os.getpid(), 'can only join a child process'
    assert self._popen is not None, 'can only join a started process'
    res = self._popen.wait(timeout)
    if res is not None:
        _current_process._children.discard(self)
from multiprocessing import Process, Queue
import time, tkinter, queue, random, sys

class Test:
    def __init__(self, root):
        self.root = root
        txt = tkinter.Text(root)
        txt.pack()

        self.q = Queue()

        p = Process(target=self.bg)
        p.start()

        self.checkqueue()
        print('__init__ done', end=' ')

    def bg(self):
        print('Starting bg loop', end=' ')
        n = 42
        while True:
            # Burn some CPU cycles
            (int(random.random() * 199999)) ** (int(random.random() * 1999999))
            n += 1
            self.q.put(n)
            print('bg task finished', end=' ')

    def checkqueue(self):
        try:
            print(self.q.get_nowait(), end=' ')
        except queue.Empty:
            print('Queue empty', end=' ')

        sys.stdout.flush()

        # Run myself again after 1 second
        self.root.after(1000, self.checkqueue)


root = tkinter.Tk()
Test(root)
root.mainloop()