Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.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/6/multithreading/4.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 访问Tkinter';由后台线程创建的文本小部件导致崩溃_Python_Multithreading_Tkinter - Fatal编程技术网

Python 访问Tkinter';由后台线程创建的文本小部件导致崩溃

Python 访问Tkinter';由后台线程创建的文本小部件导致崩溃,python,multithreading,tkinter,Python,Multithreading,Tkinter,我创建了一个简单的tkinter应用程序,其中使用了两个线程。他们的任务是将数字写入标签和文本等小部件。一个线程由按钮触发(单击事件),第二个线程作为后台线程执行 import Tkinter as tk from ttk import * from Tkconstants import * import threading, thread, time def tl1(text,counter): while True: text.insert(END,counter)

我创建了一个简单的tkinter应用程序,其中使用了两个线程。他们的任务是将数字写入标签和文本等小部件。一个线程由按钮触发(单击事件),第二个线程作为后台线程执行

import Tkinter as tk
from ttk import *
from Tkconstants import *
import threading, thread, time

def tl1(text,counter):
    while True:
        text.insert(END,counter)
        counter += 1
        time.sleep(2)

def tl2(label,counter):
    while True:
        label['text'] = counter
        counter += 1
        time.sleep(1)

class mainWindow():
    def __init__(self, master):
        self.master = master
        self._initLayout()

    def _initLayout(self):

        #button
        self.button = tk.Button(self.master, text="thread1_start", command = self._task1)
        self.button.pack()

        #label
        self.label = tk.Label(self.master)
        self.label.pack()

        #text
        self.text = tk.Text(self.master, width=30)
        self.text.pack()

    def _task1(self):
        t1 = thread.start_new_thread(tl1,(self.text,1))

    def _task2(self):
        t2 = thread.start_new_thread(tl2,(self.label,1000))

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.mainWindow = mainWindow(self)

        self.mainWindow._task2() #background_thread

app = App()
app.mainloop()
通过这种方式,一切正常,但如果我们更改背景线程以在文本小部件上显示结果,整个应用程序将冻结。

为什么后台线程可以很好地与标签通信,但会导致文本小部件出现问题?有没有办法让它正常运行

Tkinter不是线程安全的。您只能从创建小部件的线程访问它们。您的线程需要将数据放在线程安全队列中,GUI线程需要轮询队列


在您的特定情况下,您根本不需要线程。您可以使用tkinter
after
方法定期运行代码

也许您可以使用而不是实际的线程。请注意,这两个任务都是无限循环,在没有线程的情况下运行它们也会导致应用程序冻结。是的,但是如果您在之后继续使用而不是在期间使用重新注册,也许你是对的,最好的解决方案是使用从主线程管理的队列,但我想知道为什么它适用于标签小部件而不适用于文本。这些线程不会相互影响,因此理论上应该没有区别
after
用于
self.main窗口的方法。_task2()
工作,即使延迟设置为1ms(可能主要取决于应用程序的复杂性和机器硬件,无论如何它必须等待
mainloop
初始化)。线程必须被使用,没有它们应用程序窗口冻结。谢谢你提供这个解决方案。@Jarek:我不知道为什么它适用于某些小部件而不适用于其他小部件。这就是线程问题的本质——结果可能有点不确定。我建议不要使用1ms的
after
,除非你真的需要每秒执行1000次。是的,我理解你的观点-1ms不是必需的,只是为了测试目的检查一下。但请注意,在我的模式中,我只执行了一次(在这一行:
self.mainWindow.\u task2()#background\u thread
),我没有重新注册它。我的应用程序现在运行得很好-我使用队列重写了它。再次感谢布莱恩。