【问题标题】:Creating multiple instances of wx.App - is it ok?创建 wx.App 的多个实例 - 可以吗?
【发布时间】:2016-12-15 01:08:16
【问题描述】:

所以我需要实现以下场景: - 多个任务作为进程同时运行。 - 每个任务都应显示一个带有“取消”按钮的进度条,单击该按钮应终止它。

为了实现响应式GUI,我在单独的线程中为每个进程运行任务,看来我还需要为每个进程创建一个单独的wx.App,否则线程似乎没有运行。但是,此设置可以正常工作:

a) 我不确定多个wx.App 是否是个好主意或

b) 如果有更好的方法来实现我的目标。

MWE 下面(注意:在这个示例代码中,我可以使用wx.ProgressDialogUpdate 方法来识别是否已按下“取消”按钮,但对于我的实际应用程序却不能这样做)。

import wx, multiprocessing, time, psutil
from multiprocessing import Queue
from threading import Thread
from wx.lib.pubsub import pub as Publisher

#runs the task
def task_runner(q):
    pid = multiprocessing.current_process().pid
    q.put(pid)

    while True:
        print("Process Running")
        time.sleep(1)
        wx.CallAfter(Publisher.sendMessage, "update") #call to update the bar

class TestPanel():

    def __init__(self,name):
        self.q = Queue()
        self.count=0
        max = 80

        # dialog to see progress and cancel the task
        self.dlg = wx.GenericProgressDialog(name,
                               "An informative message",
                               maximum = max,
                               parent=None,
                               style = wx.PD_CAN_ABORT
                                | wx.PD_APP_MODAL
                                | wx.PD_ELAPSED_TIME
                                )

        #set listener to dialog's "Cancel" button
        for child in self.dlg.GetChildren():
            if isinstance(child, wx.Button):
                cancel_function = lambda evt, parent=self.dlg: self.onClose(evt, parent)
                child.Bind(wx.EVT_BUTTON, cancel_function)

        #subscribe to update the progress bar from the thread
        Publisher.subscribe(self.updateProgress, "update")


        # start thread which runs some task
        p = Thread(target=task_runner, args=(self.q,))
        p.start()


    #updates the progress bar
    def updateProgress(self):
        print("updating progress")
        self.count=self.count+10
        self.dlg.Update(self.count)

    #kills the process
    def kill(self, proc_pid):
            process = psutil.Process(proc_pid)
            for proc in process.children(recursive=True):
                proc.kill()
            process.kill()

    #closing the dialog event
    def onClose(self, event, dialog):
        """"""
        print "Closing dialog!"
        pid = self.q.get()
        self.kill(pid)
        dialog.Destroy()

# run process, each process creates its own wx.App
def runProcess(name):
    app = wx.App(False)
    TestPanel(name)
    app.MainLoop()


# worker class to use for multiprocessing pool
class Worker():
    def __call__(self, name):
        return runProcess(name)


if __name__ == '__main__':
    items=['Bar1', 'Bar2']
    pool = multiprocessing.Pool(processes=2)
    result = pool.map(Worker(), items) #create two processes
    pool.close()

【问题讨论】:

    标签: python multithreading python-2.7 wxpython


    【解决方案1】:

    不,在一个进程中拥有多个 wx.App 不是一个好主意。即使在先前完成后创建一个新的,有时也会有问题。

    但是,由于您使用的是multiprocess,它并不完全相同。除非我遗漏了什么,否则在您的情况下,每个操作系统进程确实只有一个 wx.App,并且由于父进程没有创建 wx.App,因此他们不会尝试继承该进程(这可能会导致更多问题.)

    【讨论】:

    • 感谢您的意见。实际上对于我的真实应用程序(不是这里的代码),父进程确实创建了一个wx.App - 我会报告出现的任何问题。然而到目前为止,我的问题是进程的终止——当用户单击“取消”时它们停止运行,但 python 任务仍然在后台运行。我可能不得不在一个单独的问题中问这个问题。
    猜你喜欢
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 2014-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多