回答編集履歴

2

修正時にまぎれた不具合修正。終了処理 _root() -> _root.quit()

2024/12/24 03:33

投稿

teamikl
teamikl

スコア8794

test CHANGED
@@ -258,7 +258,7 @@
258
258
 
259
259
  def quit(self):
260
260
  self._stop()
261
- self._root()
261
+ self._root.quit()
262
262
 
263
263
  def _stop(self): # NOTE: thread-safe
264
264
  with self._mutex:

1

不具合修正: UWSC.emit の排他制御が完全でなかったので修正。if is_running ~ after の隙間に別スレッドから終了する余地があった

2024/12/23 23:16

投稿

teamikl
teamikl

スコア8794

test CHANGED
@@ -111,7 +111,7 @@
111
111
  import tkinter as tk
112
112
  from dataclasses import dataclass
113
113
  from operator import attrgetter
114
- from threading import Thread, Event, Lock
114
+ from threading import Thread, Event, RLock
115
115
  _get_geometry = attrgetter(*"x y width height".split())
116
116
 
117
117
  def gen_timer(root, gen, timer=None): # 簡易実装版、キャンセル可能なタイマー
@@ -202,7 +202,7 @@
202
202
  self._tasks = []
203
203
  self._threads = []
204
204
  self._event = Event()
205
- self._mutex = Lock()
205
+ self._mutex = RLock()
206
206
 
207
207
  def sleep(self, interval):
208
208
  return interval
@@ -231,8 +231,9 @@
231
231
  self.tk_root.after_idle(thread.start)
232
232
 
233
233
  def emit(self, func, *args, **kw): # NOTE: thread-safe
234
- if self.is_running: # <-- ここの同期が正常に保てればスレッド安全
234
+ with self._mutex: # <-- ここの同期が正常に保てればスレッド安全
235
+ if self.is_running:
235
- self.tk_root.after_idle(lambda: func(*args, **kw))
236
+ self.tk_root.after_idle(lambda: func(*args, **kw))
236
237
 
237
238
  def run(self):
238
239
  root = self.tk_root
@@ -243,6 +244,7 @@
243
244
  cancel()
244
245
  root.update_idletasks()
245
246
  root.destroy()
247
+
246
248
  root.protocol("WM_DELETE_WINDOW", _on_closing)
247
249
 
248
250
  root.mainloop()
@@ -256,7 +258,7 @@
256
258
 
257
259
  def quit(self):
258
260
  self._stop()
259
- self._root.quit()
261
+ self._root()
260
262
 
261
263
  def _stop(self): # NOTE: thread-safe
262
264
  with self._mutex: