当前位置: 首页 > 知识库问答 >
问题:

Tkinter python多线程(避免“不响应”)

孟英叡
2023-03-14

我正试图用tkinter编写一个Python GUI程序。

我想做两根线。一个使用main_form函数运行,以防止tkinter保持更新和循环(避免“无响应”)。

另一个,当按钮1(btn1)被单击时,使函数sci_thread()开始运行,并启动执行长时间代码main_scikit的thread2。

但是tkinter一直没有回应。

下面是我的代码

import threading

class class_one:
    def main_scikit(seft):
        ######
        code_take_loooong_time
        ######
    def save(seft):
        pass

    def main_form(seft):
        root = Tk(  )
        root.minsize(width=300, height=500)
        ent1 = Entry(width=30)
        ent1.grid(row=0,column=1,padx = 10,pady=5)
        bnt1 = Button(root,text = "Start",command=lambda : seft.sci_thread())
        bnt1.grid(row=5,column=0,padx = 10) 

        root.update() 
        root.mainloop()

    def sci_thread(seft):
        maincal = threading.Thread(2,seft.main_scikit())
        maincal.start()

co = class_one()
mainfz = threading.Thread(1,co.main_form());
mainfz.start() 

共有1个答案

商开济
2023-03-14

你的应用没有响应,因为你的目标参数在声明时执行,结果作为目标传递。显然,正因为如此,当在GUI的线程中执行code_take_loooong_time时,GUI没有响应。处理它——去掉多余的括号。

请尝试以下代码段:

import threading

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class class_one:
    def main_scikit(self):
        ######
        # code_take_loooong_time
        # same as sleep
        threading.Event().wait(5)
        # some print
        self.print_active_threads_count()

        ######
    def save(self):
        pass

    def main_form(self):

        self.root = tk.Tk()
        self.root.minsize(width=300, height=500)
        self.ent1 = tk.Entry(self.root, width=30)
        self.ent1.grid(row=0, column=1, padx=10, pady=5)
        self.bnt1 = tk.Button(self.root, text="Start", command=self.sci_thread)
        self.bnt1.grid(row=5, column=0, padx=10)

        self.root.update()
        self.root.mainloop()

    def sci_thread(self):
        maincal = threading.Thread(target=self.main_scikit)
        maincal.start()

    def print_active_threads_count(self):
        msg = 'Active threads: %d ' % threading.active_count()

        self.ent1.delete(0, 'end')
        self.ent1.insert(0, msg)
        print(msg)


co = class_one()
mainfz = threading.Thread(target=co.main_form)
mainfz.start() 

链接:

  • tkinter按钮参数存在类似问题
  • 更一般:如何将方法作为参数传递
  • 线程文档

另外,启动tkinter应用程序时要小心,因为tkinter(通常)希望mainloop是最外层的循环,并且所有Tcl命令都是从同一线程调用的。所以,即使您只是想退出GUI,也可能会有更多的同步问题!总之,也许这个和那个会给你一些新的想法。

 类似资料:
  • 我正在使用的SMS网关来响应客户传入的短信。 但是,我的处理需要相当长的时间(大约20秒),在此期间,我从Twilio收到一个超时。 我在想一个防止超时的方法。我怎样才能加快处理时间?耗时最长的部分是我上传一些图像。我在想我可以在不同的线程中启动这个过程。我的服务器只有一个核心,那么多线程会有好处吗?

  • 问题内容: 我遇到的问题是,有时我启动的线程在调用它之前就完成了。看来这使我的程序等待不再发生的事情()。如何确保不等待线程完成? 问题答案: 如果您阅读JavaDocs for Thread,它将告诉您 永远不要在Thread对象上使用。您应该使用join()

  • 问题内容: 我发现我的某些活动在启动时被阻止。因此,我在一个新项目中编写了该代码: 结果是第一次创建AdView对象会阻塞UI线程1到2秒钟。 有什么办法可以避免这种情况? 谢谢 问题答案: 您正在UI线程中创建AdView,这就是被阻止的原因。在AdView初始化期间,线程不会执行其他任何操作。 您可以尝试在另一个线程中加载AdView,也可以使用AsyncTask以用户界面安全的方式加载它。

  • 下面的代码片段给我错误< code >不在FX应用程序线程上;当前线程 = < code > Java FX < code >应用程序线程。这个应用程序在java 1.7中运行良好,但是当我把它移到fx8时,它现在出现错误。当我第一次尝试启动应用程序时,它按预期工作。但是在关闭并再次打开舞台后,它不起作用了。 错误也不明确。如果当前线程是fx应用程序线程,那么不在fx应用线程上意味着什么。

  • 本文向大家介绍什么是线程死锁?如何避免死锁?相关面试题,主要包含被问及什么是线程死锁?如何避免死锁?时的应答技巧和注意事项,需要的朋友参考一下 认识线程死锁 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态

  • 这是一个关于示例项目的基本问题,因为我仍在学习Java8个特性的最佳实践。 假设我有一个OrderDetail对象,该对象表示OrderDetail的List。同时,包含一个和一个,以及和。 对于本例,我将把从移动到,这两个都是对象,具有属性,这将受到结果的影响。 现在,我需要更新所有