我正在使用tkinter拨一个GUI,当我的应用程序关闭时,我试图通过清理所有线程来成为一个负责任的公民。我的应用程序是多线程的,有一个轮询引擎定期将更新发送回我的显示器。我使用资源锁定来控制对共享资源的访问(下面的示例代码中没有显示)。问题是,在关闭应用程序窗口后,我经常被剩余的线程卡住。你知道吗
我试着在下面的代码中展示我正在使用的东西:“update”的回调是异步的。问题是,在我检查“self.\u active”查看底层小部件的状态和调用“。。。frameWidget.configure文件(样式=…“和”。。。varToUpdate.set文件(…”,tkinter引擎可能已将这些小部件的状态更改为某种风格的“失效”/“无响应”。你知道吗
使用锁没有帮助。我还没有找到一种方法来控制小部件的状态,以防止它们“死亡”,直到我可以清理东西。事件通知看起来很简单:它们告诉您发生了一个事件,但不允许您延迟小部件-“死亡”直到您可以完成清理。你知道吗
真正的问题似乎是配置小部件样式的调用(“self.frameWidget.configure配置(style=stylename)“)并更新IntVar(”self.varToUpdate.set设置(值)“)只需在GUI关闭时挂起/阻止即可。
这些方法调用永远不会返回,而不是产生异常或什么也不产生。(在我看来这不是一个好行为。)
所以。怎么处理?有什么想法吗?我真的很喜欢以某种方式将一段代码指定为“原子”的功能,这样我就可以保证在检查“.\u active”之后立即运行对象操作,但我在Python中没有看到类似的情况。即使我能做到这一点,我也不确定tkinker引擎实际上是如何更新对象的,所以这可能无法解决问题。我错过什么了吗?你知道吗
是的,我对Python还不熟悉,等等。。。我有Java的背景,所以我认为我写的很多东西肯定是“非pythonic”的。我很高兴听到你的见解,我可以改善这里的事情,以利用语言的优势。你知道吗
示例代码!你知道吗
from tkinter import *
from tkinter import ttk
from myutil import Subscriber
threshold = 20
deactivationEvents = ("Deactivate", "Destroy", "Unmap")
activationEvents = ("Activate", "Map")
# class implements/inherits "listener pattern" functionality
class MyClass(Subscriber)
def __init__(self, parentWidget):
self._active = False
self.frame = ttk.LabelFrame(parentWidget, text='something')
self.varToUpdate = IntVar()
self.bar = ttk.Progressbar(self.frame, orient=VERTICAL)
self.bar.config(mode='determinate', maximum=100, variable=self.varToUpdate)
self.moreThings()
self.bindWidgetEvents():
. more
. code
. here
# I'm using a simple boolean flag to control access here
# I've tried using threading.Lock as well, to no avail
def update(self, value):
stylename = "{}.TFrame".format("Normal" if value > threshold else "Alarm")
if self._active:
self.frame.configure(style=stylename)
self.varToUpdate.set(value)
def bindWidgetEvents(self):
widgets = [self.bar, self.frame]
self.bindActivationEvents(widgets)
self.bindDeactivationEvents(widgets)
def bindActivationEvents(self, widgets):
def activate(event):
self._active = True
for widget in widgets:
for event in activationEvents:
widget.bind("<{}>".format(event), activate)
def bindDeactivationEvents(self, widgets):
def deactivate(event):
self._active = False
for widget in widgets:
for event in deactivationEvents:
widget.bind("<{}>".format(event), deactivate)
在这种特殊情况下,将线程分配为守护进程是有效的,除非我们真正关闭应用程序,否则这并没有真正的帮助。如果我只是关上一扇窗户或一个框架呢?然后我们陷入了调用这些失效GUI项并挂起线程的方法的问题。。。你知道吗
我们需要一种方法来防止这些方法被调用,但是我们不能依赖于先检查后调用的解决方案,因为这些不是原子操作。你知道吗
还有一个主意。。。人们怎么看待这个问题?你知道吗
我们也可以简单地删除对象并添加处理,以便在调用现在不存在的对象时捕获结果异常。。。你知道吗
不幸的是,即使使用这些解决方案,我认为仍然有可能在调用GUI对象之后关闭对象。你知道吗
将后台线程设置为守护进程运行得很好
当主线程退出时,线程“t”结束
我仍然觉得tkinter方法在这种情况下的表现很差,它通过阻塞/挂起而不是引发异常
相关问题 更多 >
编程相关推荐