これはおそらく少し遅いですが、とにかく...
私自身の調査では、'when="tail"' を event_generate 呼び出しに追加するというアドバイスが見つかりました。これにより、イベントが正しくキューに入れられます。そうしないと、Tk イベント ルールがイベント キューに対しておかしな動作をする可能性があります。これは (まだ?) Tkinter で文書化されていません。
それでも、私自身の調査 (および経験!) によると、Tkinter は基本的にスレッドセーフではないことがわかりました。これは、独自のスレッドの外側で Tkinter を使用して何かを行うことを保証できないことを意味します。確かに、最も安全な方法はイベントを生成することですが、これでも定期的に例外がスローされます。これは、イベントを追加するために Tkinter 内部がスレッドセーフではないことを示しています。通常、これらの例外は存続可能であるため、再試行を使用して別のクラックを作成します。これはほとんど機能します。
retries = 3
done = False
unknownException = False
while (retries != 0) and (not done) and (not unknownException):
try:
self._applicationWindow.event_generate("<<MyNewEvent>>", when="tail")
done = True
except Tk.TclError as err:
if "application has been destroyed" in err.message:
# If application is destroyed, this event is not needed
done = True
elif ("expected boolean value but got" in err.message) or ("bad option" in err.message):
# These are bugs in Tk/Tcl/Tkinter, not in our code. They seem to be uncommon,
# and seem to be survivable. Hopefully retrying will have the system in a
# slightly different state where this doesn't happen next time.
print "Tkinter/Tk/Tcl error, retry " + str(retries)
retries = retries - 1
else:
unknownException = True
except:
unknownException = True
# Unlock afterwards
self._eventLock.release()
if not done:
# If retries haven't helped or we have an exception which isn't one we know about,
# then pass the exception up the tree.
raise
スレッドセーフでない UI レイヤーは 1 つのことです。これは設計を簡素化するものと思われるため、ほぼ許容できます。ただし、スレッドセーフでないイベント キューは、プログラミング入門クラスでは不合格にすべきです。Tkinter は壊れており、実際のアプリケーションに使用すべきではないと結論付けている場合は、クラブに参加してください。私に関する限り、Tkinter の問題に対する正しい修正は、目的に合った別の UI レイヤーを使用することです。:/
PS。Python 2.7.6 を使用しています。Python 3 の YMMV。