需要多线程GUI编程的说明

Mar*_*agh 8 python user-interface

我正在寻找一个很好的解释,需要在图形应用程序中使用多线程.在下面的示例中使用了Python,但问题不是特定于python,它可能适用于任何语言的图形编程的一般设计.

让我们举一个简单的例子.假设有一个应用程序对文件集合执行某种耗时的操作,并将其输出到控制台.让我们假设此操作每个文件需要2秒,并且有10个文件要处理,名为1.txt,2.txt,3.txt,... 10.txt.然后,示例实现可能如下所示:

安慰

import time
def process(file):
    print 'processing {0}...'.format(file)
    time.sleep(2.0) #simulate slow operation

files = ['{0}.txt'.format(i) for i in range(1, 11)]
map(process, files)
Run Code Online (Sandbox Code Playgroud)

控制台示例当然是单线程的,并且工作正常.现在,如果我们想要添加图形进度条,单线程实现可能如下所示:

单线程gui

import time, gtk, gobject

def process(file):
    print 'processing {0}...'.format(file)
    time.sleep(2.0)

class MainWindow(gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.progress = gtk.ProgressBar()
        self.progress.set_fraction(0)
        self.add(self.progress)
        self.connect("destroy", gtk.main_quit)
        self.show_all()
        files = ['{0}.txt'.format(i) for i in range(1, 11)]
        gobject.timeout_add(100, self.submit, files, 0)

    def submit(self, files, i):
        process(files[i])
        self.progress.set_fraction((i + 1.0)/len(files))
        if i + 1 < len(files):
            gobject.idle_add(self.submit, files, i + 1)

win = MainWindow()
gtk.main()
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常,但是当您运行应用程序时,如果您尝试与应用程序交互,例如尝试并调整窗口大小,例如它将会卡住,并且只有在它被释放以处理待处理的gui事件时每两秒响应一次.最后一个示例是一个多线程实现,并在整个执行过程中保持响应.

多线程gui

import time, gtk, gobject, threading

def process(file):
    print 'processing {0}...'.format(file)
    time.sleep(2.0)

class MainWindow(gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.progress = gtk.ProgressBar()
        self.progress.set_fraction(0)
        self.add(self.progress)
        self.connect("destroy", gtk.main_quit)
        self.show_all()
        files = ['{0}.txt'.format(i) for i in range(1, 11)]
        threading.Thread(target=self.submit, args=(files,)).start()

    def submit(self, files):
        for i, file in enumerate(files):
            process(file)
            gobject.idle_add(self.progress.set_fraction, (i + 1.0)/len(files))
            if not self.get_visible():
                return

gtk.gdk.threads_init()
win = MainWindow()
gtk.main()
Run Code Online (Sandbox Code Playgroud)

对我来说,如果你在代码中有一个长时间运行的阻塞操作,并且你想要一个响应的gui,你必须使用多线程解决方案,这似乎是非常清楚和合乎逻辑的.没有别的办法了.是这样的吗?我试图向其他开发人员多次解释,但许多人不理解或不同意.有人可以提供这个概念的解释,链接到它上面的文章,或者如果我的理解不正确,请纠正我.

sie*_*z0r 7

你的理解是正确的.如果应用程序不是多线程的,则应用程序会等待每个操作完成.当您的应用程序是多线程时,您使用一个线程来处理GUI操作,而另一个线程来处理文件.

我没有文章或类似的东西的引用.如果你认为线程是人,每个人都有自己的工作,每个人一次只做一件事,也许会有所帮助.