TkInter 死锁

0 投票
1 回答
705 浏览
提问于 2025-04-18 04:00

下面的代码有什么问题吗?我运行类似的代码时遇到了死锁的情况,也就是说,如果主线程试图获取已经被锁住的锁,循环就不会释放这个锁。

另外,由于我不能在没有“添加更多细节”的情况下发布这个内容,那么在这种情况下,哪些细节比较好呢?

import Tkinter
import threading
from time import sleep
from random import random

class Test(Tkinter.Tk):

    def __init__(self, parent):
        Tkinter.Tk.__init__(self, parent)
        self.resizable(False, False)
        self.grid()
        self._button = Tkinter.Button(self, text='Click me', command=self._foo)
        self._button.grid(column=0, row=0)
        self._lock = threading.Lock()

    def __enter__(self):
        self._loopRunning = True
        self._loopThread = threading.Thread(target=self._loop)
        self._loopThread.start()
        return self

    def __exit__(self, exc_type, exc_val, traceback):
        self._loopRunning = False
        self._loopThread.join()
        return False

    def _loop(self):
        while self._loopRunning:
            print 'loop wants lock'
            with self._lock:
                print 'loop acquired lock'
                self._button.configure()
                sleep(random())
                print 'loop should release lock'
            print 'loop released lock'
            sleep(1)

    def _foo(self):
        print 'foo wants lock'
        with self._lock:
            print 'foo acquired lock'
            self._button.configure()
            sleep(random())
            print 'foo should release lock'
        print 'foo released lock'
        sleep(1)

if __name__ == '__main__':
    with Test(None) as test:
        test.mainloop()

1 个回答

3

Tkinter 这个库在多线程中不太安全。如果你想在 Tkinter 中进行操作,最好使用一个队列,或者使用一个线程安全的版本叫 mtTkinter(可以在这里查看:http://tkinter.unpythonic.net/wiki/mtTkinter)。我选择了 mtTkinter。

很抱歉之前没有仔细查看已经问过的问题。这个问题之前已经有人讨论过,比如:

使用线程的 Tkinter 脚本在创建第二个 Toplevel 窗口时崩溃

Tkinter 应用中的可能锁定问题

Tkinter:如何使用线程防止主事件循环“冻结”

撰写回答