GUI

Python Tkinter Event Loop(5) スレッド/プロセス

長時間実行される計算を、それぞれが素早く実行される個別に分割することが不可能であったり、非現実的であったりする場合があります。または、非同期処理をサポートしないライブラリを使う場合もある。Pythonのasyncioのように、Tkのイベントループとうまく連携できないこともある。そのような場合、Tk GUI の応答性を維持するために、時間のかかる操作やライブラリの呼び出しをイベントハンドラの外に出して、どこか別の場所で実行する必要がある。スレッド、あるいは他のプロセスがその助けとなる。

スレッドでタスクを実行したり、スレッドと通信したりすることは、このチュートリアルの範囲外。しかし、Tk をスレッドで使用する際には、注意すべきいくつかの制約がある。主なルールは、Tk をロードしたスレッドからしか Tk を呼び出さないというもの。

Tkinter は内部的には、複数のスレッドから Tkinter の呼び出しをメインスレッド (Tk インスタンスを生成したスレッド) にルーティングできるように、多大な努力を払っている。これはほとんどうまくいくが、常にというわけではない。よって、Tkinterの呼び出しはすべて1つのスレッドで行うことが推奨される。

他のスレッドから Tkinter を実行しているスレッドに通信する必要がある場合は、できるだけ単純にすべきだ。event_generate を使って Tkinter のイベントキューに仮想イベントをポストし、コード内でそのイベントにバインドする。

root.event_generate("<<MyOwnEvent>>")

さらに複雑にすることも可能。Tcl/Tk ライブラリは、スレッドサポートありでもなしでもビルドできる。アプリケーションに複数のスレッドがある場合、スレッドビルドで実行されていることを確認すること。不明な場合は、Tcl変数tcl_platform(threaded)を確認すること(これは0ではなく、1であるべき)。

>>> tkinter.Tcl().eval('set tcl_platform(threaded)')