Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.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/user-interface/2.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 解释多线程GUI编程的需求_Python_User Interface - Fatal编程技术网

Python 解释多线程GUI编程的需求

Python 解释多线程GUI编程的需求,python,user-interface,Python,User Interface,我正在寻找一个很好的解释,说明在图形应用程序中使用多线程的必要性。在下面的示例中,使用了Python,但问题并非特定于Python,它可能适用于任何语言中图形编程的一般设计 让我们举一个简单的例子。假设有一个应用程序对一组文件执行某种耗时的操作,并将其进度输出到控制台。让我们假设此操作每个文件需要2秒钟,并且有10个文件需要处理,分别称为1.txt、2.txt、3.txt。。。10.txt。然后,示例实现可能如下所示: 控制台 import time def process(file):

我正在寻找一个很好的解释,说明在图形应用程序中使用多线程的必要性。在下面的示例中,使用了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)
控制台的例子当然是单线程的,并且做得很好。现在,如果我们想添加图形进度条,单线程实现可能如下所示:

单线程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()
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()

在我看来,如果您的代码中有一个长期运行的阻塞操作,并且您想要一个响应性强的gui,那么您就必须使用多线程解决方案,这似乎是非常清楚和合乎逻辑的。没有别的办法了。是这样吗?我曾多次尝试向其他开发人员解释这一点,但许多人不理解或不同意。有人能提供这个概念的解释,一个关于它的文章的链接,或者纠正我,如果我的理解是错误的

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


我没有类似的文章或参考文献。如果你把线程看作人,每个线程都有自己的工作,每个线程一次只能做一件事,这可能会有所帮助。

多线程是实现这一点的一种方法,但不一定是唯一(或最好)的方法。作为python示例,提供一种在同一线程内运行并发进程的方法,避免与多线程相关的锁定问题。当然,在大多数情况下,我都认为GLILLET是首选的解决方案,因为编码相对容易。

主要原因是GUI工具包处理了主环< /代码>中的所有事件(鼠标移动、按钮单击、键盘输入、系统事件等)。这不是为GUI应用程序编写的代码的一部分

此主循环调用您提供的所有事件处理程序和其他函数。现在,如果其中一个函数花费的时间太长(例如>100ms),那么会对UI响应产生非常明显的影响,因为主循环将无法处理更多的事件


无论使用何种工具包的编程语言,本主题都应在任何GUI编程书籍的“高级概念”部分详细讨论。

您是否可以使用greenlets发布一些代码,使用相同的过程函数,并列出问题中的文件。我想比较一下,我认为你说的不对。您可以使用任何具有阻塞调用且仍然具有响应GUI的库发布一个示例图形python代码吗。这根本没有道理。对不起,我的回答不太清楚。我回答的是并发性是否=多任务的一般问题。要用greenlet重新编写示例,需要更多关于
process\u files
函数的详细信息,因为这是您希望封装在greenlet中的函数,如果无法访问,则您肯定需要多线程。您的理解是正确的。假设您有一个压缩大文件的GUI应用程序。如果您单击一个按钮并开始压缩(单线程),您肯定会看到窗口冻结,而重画不会发生。aI建议将术语“进程”替换为“操作”或其他,因为进程可能会被解释为操作系统进程,而且它是不明确的。我是这样做的,但我更愿意将选择权留给作者:)