저는 tkinter를 사용하여 GUI를 다이얼링하고 있습니다. 응용 프로그램이 닫히면 모든 스레드를 정리하여 책임있는 시민이 되고자합니다. 내 응용 프로그램은 폴링 엔진이 정기적으로 업데이트를 내 디스플레이에 다시 보내는 멀티 스레드입니다. 공유 리소스에 대한 액세스를 제어하기 위해 리소스 잠금을 사용하고 있습니다 (아래의 예제 코드에는 표시되지 않음). 문제는 응용 프로그램 창을 닫은 후 꽤 자주 남은 스레드가 붙어 있다는 것입니다.tkinter (파이썬 GUI) 위젯을 제거하는 호출이 걸려 있습니다.
아래 코드에서 내가 작업하고있는 것을 보여 주려고했습니다. "업데이트"콜백이 비동기입니다. 문제는 기본 위젯의 상태에 대해 "self._active"를 확인한 시간과 "... frameWidget.configure (style = ..."및 "..." varToUpdate.set (... "), 위젯의 상태가 tkinter 엔진에 의해 'defunct'/ 'unresponsive'의 일부 풍으로 변경되었을 수 있습니다 ..
잠금을 사용하면 도움이되지 않습니다. 방법을 정리할 때까지 위젯의 상태를 제어하여 '죽어가는'일이 없도록합니다. 이벤트 알림은 간단히 나타납니다. 이벤트가 발생했음을 알려주지 만 위젯을 지연시키지 않습니다. 청소를 마칠 때까지 '죽음'
실제 문제는 위젯의 스타일을 구성하는 호출 ("self.frameWidget.configure (style = stylename) ") 및 IntVar ("self.varToUpdate.set (value) ")를 업데이트하려면 GUI가 종료 될 때 단순히 멈추거나 차단하십시오.
예외를 생성하거나 아무 것도 산출하지 않고 이러한 메서드 호출이 반환되지 않습니다. (이것은 나에게 좋은 행동처럼 보이지 않습니다.)
그래서. 이 문제를 어떻게 처리할까요? 어떤 아이디어? 어떻게 든 "원자"라는 코드 덩어리를 지정하는 것을 좋아해서 객체 조작이 "._active"에 대한 검사가 끝난 직후에 실행되도록 보장 할 수 있었지만 Python에서 그런 것을 보지 못했습니다. . 이를 달성 할 수 있다고해도, tkinker 엔진이 실제로 오브젝트를 업데이트하는 방법에 대해 확신하지 못하기 때문에 문제가 해결되지 않을 수 있습니다. 내가 놓친 게 있니?
그렇습니다. 저는 파이썬을 처음 접했습니다. bla bla bla ... 저는 자바 배경에서 왔기 때문에, 필자가 작성한 것 중 많은 부분이 확실히 "파이썬이 아닌 것"이라고 가정합니다. 나는 언어의 강점을 활용하기 위해 어떻게 개선 할 수 있는지에 대한 당신의 통찰력을 듣게되어 매우 기쁩니다.
예제 코드! 데몬이 잘
t = Thread(target=self.pollData)
t.daemon = True
t.start()
스레드 't'를 작업으로 메인 스레드가
이 난 아직도/매달려를 차단함으로써 Tkinter의 방법이 제대로 작동하는지 느낌이 종료 할 때
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)
스레드 스레드 데몬을 만들어 상위 스레드와 함께 죽게하십시오. – Novel
글쎄, 그건 분명히 효과가있다! 나는 아직도 그 방법들이 매달리기보다는 예외를 제기해야한다고 생각한다. 고마워요! –