2017-04-05 2 views
0

私はtkinterを使用してGUIにダイヤルアップしています。アプリケーションが終了したときにスレッドをすべてクリーンアップして責任ある市民になろうとしています。私のアプリケーションはマルチスレッドで、ポーリングエンジンは定期的にアップデートをディスプレイに送り返します。私は共有リソースへのアクセスを制御するためにリソースロックを使用しています(下のサンプルコードには示されていません)。問題は、非常に頻繁にアプリケーションウィンドウを閉じた後、残っているスレッドに悩まされていることです。tkinter(python GUI)ウィジェットが無効になるまでの呼び出し

私は以下のコードで私が作業していることを示してみました: "更新"のコールバックは非同期です。問題は、基礎となるウィジェットのステータスを「self._active」にチェックしてから、「... frameWidget.configure(style = ...」および「...」を呼び出した時刻varToUpdate.set(... ")これらのウィジェットの状態は、tkinterエンジンによって「無効」/「応答なし」という風味に変更されている可能性があります。

ロックを使用するとヘルプが表示されません。ウィジェットの状態を制御して、私が物事をきれいにするまで瀕死状態にならないようにしますイベント通知は単にイベントが発生したと伝えますが、

本当の問題は、ウィジェットのスタイルを設定するための呼び出し( "self.frameWidget.configure( GUIがシャットダウンされたときに単にハング/ブロックするだけで、IntVar( "self.varToUpdate.set(value)")を更新することができます。
例外を生成するのではなく、何も返さない場合、これらのメソッド呼び出しは返されません。 (これは私にとっては良い行動ではないようです。)

So.これに対処する方法は?何か案は?私は本当に "原子"としてのコードのチャンクを何とか指定することが大好きです。オブジェクト操作が "._active"のチェックの直後に実行されることが保証されていましたが、Pythonのようなものは見たことがありません。私がそれを達成することができたとしても、tkinkerエンジンが実際にオブジェクトを更新する方法がわからないので、問題を解決できない可能性があります。何か不足していますか?

はい、私はPython、bla bla blaを初めて使っています...私はJavaの背景から来ているので、私が書いたことの多くは確かに "非python"であると仮定します。私は言語の強みを活かすために、ここでどのように改善するかもしれないかについてのあなたの洞察を聞いて本当にうれしく思います。

サンプルコード!

デーモンが「T」は、メインスレッドが

を終了したとき、私はまだTkinterの方法は、ブロッキング/ハングによって不完全に振る舞うことを感じて終わるだけで結構

t = Thread(target=self.pollData) 
t.daemon = True 
t.start() 

スレッドを働いたとして、バックグラウンドスレッドを設定

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) 
+0

スレッドスレッドのデーモンを親スレッドで終了させるだけです。 – Novel

+0

まあ、それは確かに働いた!私はまだ、それらの方法は、彼らが行う方法をぶら下げるよりも例外を提起する必要があるように感じる...ありがとうございます! –

答えて

0

このシナリオで例外を発生させるのではなく、

0

デーモンとしてスレッドを割り当てるのはこの特定のケースでは機能しますが、私たちが実際にアプリケーションを終了します。私が単に窓やフレームを閉めていたら?これらのメソッドが呼び出されないようにする方法が必要ですが、チェックには依存できません。これはアトミック操作ではないためです。

これは別のアイデアです...人々はこれを解決策と考えていますか?

我々はまた、単にオブジェクトを削除し、呼び出しが今非existantオブジェクトに対して行われたときに結果の例外をキャッチするために扱う追加される場合があります
# The tkinter GUI objects were hanging indefinitely upon calls to their methods after 
    # the window was closed, so we will replace them with dummy objects that will recieve 
    # those calls instead 
    def deactivate(self): 
    self._active = False 
    self.varToUpdate = Stub() # we could probably just reinitialize an IntVar 
    self.bar = Stub() 
    self.frame = Stub() 

class Stub(object): 

    def __init__(self): 
    pass 

    def config(self, **kwargs): 
    pass 

    def set(self, value): 
    pass 

...

def deactivate(self): 
    self._active = False 
    del self.varToUpdate 
    del self.bar 
    del self.frame 

残念ながら、でも、これらのソリューションで、私はまだGUIオブジェクトへの呼び出しが行われた後にオブジェクトのシャットダウンが発生する可能性があると思います。

関連する問題