Python 解释多线程GUI编程的需求
我正在寻找一个很好的解释,说明在图形应用程序中使用多线程的必要性。在下面的示例中,使用了Python,但问题并非特定于Python,它可能适用于任何语言中图形编程的一般设计 让我们举一个简单的例子。假设有一个应用程序对一组文件执行某种耗时的操作,并将其进度输出到控制台。让我们假设此操作每个文件需要2秒钟,并且有10个文件需要处理,分别称为1.txt、2.txt、3.txt。。。10.txt。然后,示例实现可能如下所示: 控制台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):
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编程书籍的“高级概念”部分详细讨论。您是否可以使用greenlets发布一些代码,使用相同的过程函数,并列出问题中的文件。我想比较一下,我认为你说的不对。您可以使用任何具有阻塞调用且仍然具有响应GUI的库发布一个示例图形python代码吗。这根本没有道理。对不起,我的回答不太清楚。我回答的是并发性是否=多任务的一般问题。要用greenlet重新编写示例,需要更多关于
process\u files
函数的详细信息,因为这是您希望封装在greenlet中的函数,如果无法访问,则您肯定需要多线程。您的理解是正确的。假设您有一个压缩大文件的GUI应用程序。如果您单击一个按钮并开始压缩(单线程),您肯定会看到窗口冻结,而重画不会发生。aI建议将术语“进程”替换为“操作”或其他,因为进程可能会被解释为操作系统进程,而且它是不明确的。我是这样做的,但我更愿意将选择权留给作者:)