在 Tkinter 中执行函数期间程序冻结

Posted

技术标签:

【中文标题】在 Tkinter 中执行函数期间程序冻结【英文标题】:Program freezing during the execution of a function in Tkinter 【发布时间】:2012-06-06 12:55:00 【问题描述】:

我为我的一个脚本创建了一个小 GUI。一切运作良好。

当我单击一个按钮时,它会启动一项大功能,该功能正在解析来自某些网站的大量数据。

但是一旦我点击了按钮,程序就会冻结,直到函数完全运行。一切正常,但为什么我的 GUI 在函数执行期间冻结。 我想打印一个小进度条,但这是不可能的。

这是程序的一部分:

    self.Button1 = Button(self.MENU, text="IELTS", command=self.My_Command)
    self.Button1.grid(row=0, column=0,sticky=W+E)

def My_Command(self):

    ## HERE WE LAUNCH THE FUNCTION
    Module_1.main() # My Big Function from another file

    self.Button1.config(text="DONE")

在执行 Module_1.main() 期间我不能做/打印任何事情...... GUI 完全冻结了。

Module_1.main() 函数是一个线程解析器(解析来自两个网站的一些数据),运行时间一般为 2 分钟。如果有人想在执行此功能所需的 2 分钟内与程序进行交互,那将非常有帮助。

【问题讨论】:

这对于 codereview.stackexchange.com 来说可能是一个更好的主题。听起来您的解析应该在一个单独的线程中而不是(即使您说它是线程的)我认为需要更多上下文来回答这个问题,您能否提供指向 github、ideone.com 或 pastebin 上完整代码的链接.com? 很糟糕,我现在无法访问代码,但你给了我一个答案。解析器是线程的,但函数不是。所以我需要把函数和GUI放在两个单独的线程中......!谢谢 ;) @Brady:不再需要上下文。这是一个众所周知的 Tkinter 反模式。 @BryanOakley,我也想通了,谢谢 【参考方案1】:

Tkinter 是单线程的。屏幕更新发生在事件循环的每次行程中。每当您有一个长时间运行的命令时,您都会阻止事件循环完成迭代,从而阻止事件处理,从而阻止重绘。

您唯一的解决方案是 a) 为长时间运行的命令使用线程,b) 为长时间运行的命令使用进程,或 c) 将命令分成小块,每个小块都可以在几毫秒内运行,这样你可以在事件循环的后续迭代中运行一个块。您还有另一种解决方案,即定期调用小部件的 update_idletasks 方法,但这更像是一种解决方法而不是修复。

请记住,Tkinter 不是线程安全的,因此使用线程需要格外小心。您只能从主线程调用小部件上的方法,这意味着其他线程必须通过线程安全队列与主线程通信。

【讨论】:

非常感谢您的回答!这一点现在已经很清楚了。我将尝试使用线程来执行长时间运行的命令。非常感谢:-)(顺便说一句,B)解决方案是什么,使用过程? ) 嗯,还有一个问题(抱歉)--> pastebin.com/yEGb8MuT 这是我想通过单击按钮执行的功能......但我想要这个功能在 Tkinter 的“背景”中工作。我很发现 Tkinter,所以如果你能让我走上一个好的轨道,那应该很棒。正如你所看到的,这个函数实际上是线程化的......所以你确定我可以线程化 Tkinter & The Function 吗?

以上是关于在 Tkinter 中执行函数期间程序冻结的主要内容,如果未能解决你的问题,请参考以下文章

使用 Tkinter 在 GIF 中播放动画 [重复]

调用 tkinter askopenfilename 方法后打开文件对话框冻结

树莓派、tkinter 和线程

iOS 应用程序在解析异步查询期间冻结

Tkinter GUI 冻结 - 解除阻塞/线程的提示?

TKinter (filedialog.askdirectory) 冻结 Spyder 控制台