当前位置: 首页 > 知识库问答 >
问题:

wxPython非阻塞GUI线程和多处理?

郑正阳
2023-03-14

Python 2.7。3 x64 wxPython 2.8 x64

我已经阅读了很多关于python线程和多处理的文章,特别是Doug Hellmann的一些文章,这些文章帮助很大。然而,我对一件事感到困惑。。。

我认为Python多处理模块或多或少是线程模块的替代品,只是args必须是可拾取的,但是我发现为了不阻塞我的GUI,我必须首先使用线程创建一个新线程。线程,然后在该线程内通过多处理进行多处理。过程这很有效,效果也不错,但对我来说似乎有点笨拙。

如果我尝试直接进行多处理而不首先执行线程,那么我的GUI仍然会阻塞,直到多处理工作完成。这是按设计进行的,还是我缺少了多处理模块的一些基本功能?

如果需要示例,我可以提供它们。

谢谢

-RMWChaos

一个例子被要求...

假设onProcess()是由GUI中的按钮触发的,这会阻止GUI。。。

import time
import multiprocessing as mp

def myWorker(a, b):
    time.sleep(0.1)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    jobs = mp.cpu_count() * 2
    a = 5
    b = 10

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

虽然这不。。。

import time
import multiprocessing as mp
import threading as th

def myWorker(a, b):
    time.sleep(0.1)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    a = 5
    b = 10
    th.Thread(target = myThread, args = [a, b,]).start()

def myThread(a, b):
    jobs = mp.cpu_count() * 2

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

共有2个答案

单于奇略
2023-03-14

我尝试在以下测试程序中运行您的代码,多处理工作正常,没有任何内容被阻止:

import time
import multiprocessing as mp
import wx


def myWorker(a, b):
    time.sleep(10)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    jobs = mp.cpu_count() * 2
    a = 5
    b = 10

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

def onGUI(event):
    print 'GUI is not blocked'

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
       wx.Frame.__init__(self, parent, id, title)
       buttons = []
       panel = wx.Panel(self, wx.ID_ANY)
       sizer = wx.BoxSizer(wx.VERTICAL)
       gui_proc_btn = wx.Button(panel, wx.ID_ANY, 'GUI Process')
       other_proc_btn = wx.Button(panel, wx.ID_ANY, 'Other process')

       gui_proc_btn.Bind(wx.EVT_BUTTON, onGUI)
       sizer.Add(gui_proc_btn, 0, wx.ALL, 5)
       other_proc_btn.Bind(wx.EVT_BUTTON, onProcess)
       sizer.Add(other_proc_btn, 0, wx.ALL, 5)
       panel.SetSizer(sizer)

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'test.py')
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

if __name__ == '__main__':

    app = MyApp(0)
    app.MainLoop()

从你的命令行运行它,按下第二个按钮(这使用多重处理在你的函数上,我增加了睡眠时间),然后按下第一个按钮。你应该注意到当按下第一个按钮时会产生输出,所以程序是没有堵塞。

夹谷沛
2023-03-14

多线程和多处理是根本不同的。

线程大部分用于i/o。创建新线程时,它包含在与生成线程的程序相同的进程中。这意味着它与程序共享内存空间,但它们(程序和线程)不能并行运行(同时查找GIL)。

另一方面,多处理在操作系统级别上产生了一个新的进程。这个新进程可以与预先存在的进程并行运行,但它不与生成它的程序共享内存空间。当您想要加速的代码与输入/输出无关,而是实际的处理器密集型计算时,这更有用。

对于gui,您主要希望对gui的不同部分使用线程,以便在gui的一个部分中运行某些东西不会锁定整个gui,直到处理结束。

没有代码很难说,但我相信您不应该特别需要在新线程中生成一个进程,而是让该线程处理这个进程。但是,如果该线程需要处理密集的计算类型的处理,而不是大量的i/o,那么您需要启动一个进程来处理它。

我相信你的大部分问题在于误解多处理vs多线程。

 类似资料:
  • 摘要 本文描述了使用 QEMU 运行 RT-Thread 提供的基于多线程的非阻塞 socket 编程示例。 简介 随着物联网的发展,越来越多产品需要基于网络进行数据传输。在实际开发中,往往要求网络传输时不能阻塞当前线程,以致无法及时处理其他消息。在用户无法直接套用简单的 socket demo 时,RT-Thread 提供基于多线程的非阻塞 socket 编程示例,方便用户进行应用程序开发。 在

  • 我正在尝试用Python编写一个程序。我想写的是一个脚本,它会立即向用户返回一条友好的消息,但会在后台生成一个长的子进程,它会处理几个不同的文件,并将它们写入一个祖父文件。我已经做了一些关于线程和处理的教程,但我遇到的是,无论我尝试什么,程序都会一直等待,直到子进程完成,然后才会向用户显示前面提到的友好消息。以下是我尝试过的: 线程示例: 我读过这些关于多线程的SO帖子如何在Python中使用线程

  • 我有下面的代码片段,它试图在多个子进程之间分割处理。 while循环中的主进程正在调用search函数,如果队列达到阈值计数,则处理池将映射到进程函数,其中作业来自队列。我的问题是,python多处理池是在执行期间阻塞主进程,还是立即继续执行?我不想遇到这样的情况,“has_jobs_to_process()”的计算结果为true,并且在处理作业的过程中,另一组作业的计算结果为true,并且再次调

  • 我完全混淆了,,。 哪个是阻塞,哪个不是? 我的意思是如果我使用父进程是否等待子进程返回/才继续执行。 如何影响这些调用?

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所

  • 如另一个问题中所述,当使用Undertow时,所有处理都应该在专用的工作线程池中完成,如下所示: 我知道可用于显式地告诉Undertow在专用的线程池中调度请求以阻止请求。我们可以通过将包装在实例中来修改上面的示例,如下所示: 调用此方法将exchange置于阻塞模式,并创建一个BlockingHttpExchange对象来存储流。当交换处于阻塞模式时,输入流方法变得可用,除了阻塞和非阻塞模式之间