teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

改善例を追記

2021/10/14 12:13

投稿

teamikl
teamikl

スコア8817

answer CHANGED
@@ -27,7 +27,38 @@
27
27
  - root.title の部分を print に変更すると、GUIへのアクセスは発生しない為、エラーは起こりません。
28
28
  - daemon スレッドにする場合も同様ですが、タイミング次第では起こる可能性は残ります(意図的な再現は難しい)
29
29
 
30
+ 上で提示したコードの改善例
31
+ ```python
32
+ from threading import Thread, Event
33
+ import tkinter as tk
30
34
 
35
+ def worker(root, event):
36
+ for num, _ in enumerate(range(5), start=1):
37
+ print(num)
38
+ if event.is_set():
39
+ break
40
+ root.title(f"{num}")
41
+ # NOTE: time.sleep では、メインスレッドで thread.join 時に GUIがフリーズする為、
42
+ # 中断可能な Event.wait を利用。
43
+ event.wait(1)
44
+
45
+ root = tk.Tk()
46
+ event = Event()
47
+ event.clear()
48
+ thread = Thread(target=worker, args=(root, event))
49
+
50
+ def on_close():
51
+ event.set() # 修了を通知
52
+ thread.join() # workerの完了を待つ
53
+ root.destroy() # GUIの破棄 (ウィンドウを閉じる)
54
+ root.protocol("WM_DELETE_WINDOW", on_close)
55
+
56
+ root.after(1000*1, thread.start)
57
+ root.after(1000*3, on_close)
58
+ root.mainloop()
59
+ ```
60
+
61
+
31
62
  ----
32
63
  暫定的な回避策
33
64
 

2

問題点の追記

2021/10/14 12:13

投稿

teamikl
teamikl

スコア8817

answer CHANGED
@@ -1,6 +1,37 @@
1
- デーモンスレッドを使わない場合、暫定的な回避策
1
+ 問題点: サブスレッドからGUIの直接操作
2
2
 
3
+ メインスレッド終了後(GUIが破棄された後) に、サブスレッドがGUIにアクセスする事になる為、
4
+ 問題が起こります。
5
+ デーモンスレッドの場合(その他の子スレッドがない場合)、サブスレッドも終了される為
6
+ 問題が発生しません。
7
+
8
+ 意図的に同じ問題を起こすコード
3
9
  ```python
10
+ from threading import Thread
11
+ import tkinter as tk
12
+
13
+ def worker(root):
14
+ import time
15
+ for num in range(5):
16
+ root.title(f"{num}")
17
+ time.sleep(1)
18
+
19
+ root = tk.Tk()
20
+ thread = Thread(target=worker, args=(root,))
21
+
22
+ root.after(1000*1, thread.start) # 1秒後に開始
23
+ root.after(1000*3, root.quit) # 3秒後にGUIを終了
24
+ root.mainloop()
25
+ ```
26
+
27
+ - root.title の部分を print に変更すると、GUIへのアクセスは発生しない為、エラーは起こりません。
28
+ - daemon スレッドにする場合も同様ですが、タイミング次第では起こる可能性は残ります(意図的な再現は難しい)
29
+
30
+
31
+ ----
32
+ 暫定的な回避策
33
+
34
+ ```python
4
35
  root.protocol("WM_DELETE_WINDOW", func)
5
36
  ```
6
37
 

1

書式の修正

2021/10/14 12:04

投稿

teamikl
teamikl

スコア8817

answer CHANGED
@@ -1,8 +1,3 @@
1
- 問題個所は特定されいて、
2
- デーモンスレッドにするという回避策も見出されているようなので、
3
- その他の方法の
4
-
5
- ----
6
1
  デーモンスレッドを使わない場合の、暫定的な回避策
7
2
 
8
3
  ```python