回答編集履歴

2

Event.wait を使ったサンプルを削除。誤誘導になる為 / 追記: 2つのスレッドで実装

2021/06/25 04:17

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -64,80 +64,62 @@
64
64
 
65
65
  ----
66
66
 
67
- ボタンによる別スレッドの停止のデモ (threading.Event の使い方サンプル)
68
-
69
- ```python
70
-
71
- import tkinter as tk
72
-
73
- import threading
67
+ 解説: 2つのスレッドで実装する
74
-
75
- import time
76
68
 
77
69
 
78
70
 
71
+ 問題点:
79
72
 
73
+ Lockで排他制御する場合、GUI等のイベント駆動プログラミングでは
80
74
 
81
- def slideshow(event):
75
+ ロック獲得によるブロックが発生すると、ウィンドウのフリーズに繋がる為、
82
76
 
83
- # スライドショーの代替として
84
-
85
- while True:
77
+ 避ける傾向があります。
86
-
87
- event.wait() # ボタンが押されるとここで止る / もう一度で再開
88
-
89
- print("tick") # ループが稼働しているのを確認する為に表示
90
-
91
- time.sleep(0.5)
92
78
 
93
79
 
94
80
 
95
- pause = threading.Event()
81
+ 解決策: 代案としては、プログラムの構造自体を
96
82
 
83
+ リソース毎に担当のスレッドを決めて、そのリソースは担当のスレッドからしか操作しないように、
84
+
97
- pause.set()
85
+ もし外部から操作したい場合は、queue 等を用いてスレッド間の通信で行う、とします。
86
+
87
+ 今回のケースであれば、対象のリソースは tkinter と cv2 の2つに別ける。
98
88
 
99
89
 
100
90
 
101
-
102
-
103
- thread = threading.Thread(
104
-
105
- target=slideshow, args=(event,), daemon=True)
91
+ ![イメージ説明](f8d72b3b9b2159caddabae3c56e70d4f.png)
106
92
 
107
93
 
108
94
 
109
- def click(e):
95
+ 起動時
110
96
 
111
- if event.is_set():
97
+ - Sub(cv2): 準備後に、tkinter起動を待機 `tk_started.wait()`
112
98
 
113
- e.widget.config(text="start")
99
+ - Main(tk): tkinter を起動
114
100
 
115
- pause.clear()
101
+ - Main(tk): イベントループを開始。tk_started.set() で Subスレッドの待機を解除
116
102
 
117
- else:
118
-
119
- e.widget.config(text="stop")
103
+ - Sub(cv2): イベントループ開始。スライドショー
120
-
121
- pause.set()
122
104
 
123
105
 
124
106
 
125
- root = tk.Tk()
107
+ 停止処理
126
108
 
127
- button = tk.Button(root, text="stop")
109
+ - Main(tk): shared.pause = True
128
110
 
129
- button.bind("<Button-1>", click)
111
+ - Sub(cv2): c2.waitKey(1) を呼び続けるループに入る(イベントループ継続の為)
130
-
131
- button.pack()
132
-
133
- root.after_idle(thread.start)
134
-
135
- root.mainloop()
136
-
137
- ```
138
112
 
139
113
 
140
114
 
141
- 注意: event.wait() はイベントループ内では使わない事。
115
+ 終了処理
142
116
 
117
+ - Main(tk): shared.running = sharead.pause = False (停止状態解除と稼働フラグをオフに)
118
+
143
- マウス・キー入力処理できくてウィドウがフリズします。
119
+ - Sub(cv2): フラグオフにったことにより、イベトルプを抜けて終了
120
+
121
+
122
+
123
+ ----
124
+
125
+ 訂正: ~~ボタンによる別スレッドの停止のデモ (threading.Event の使い方サンプル)~~

1

補足

2021/06/25 04:17

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -58,7 +58,7 @@
58
58
 
59
59
  - cv2.waitKey 等は入力所得が競合する為、何らかの対策が必要です。
60
60
 
61
-  → tkinterでキー入力を拾い、別スレッドへはthreading.Event を使い通知
61
+  → tkinterでキー入力を拾い、別スレッドへ通知
62
62
 
63
63
 
64
64
 
@@ -135,3 +135,9 @@
135
135
  root.mainloop()
136
136
 
137
137
  ```
138
+
139
+
140
+
141
+ 注意: event.wait() はイベントループ内では使わない事。
142
+
143
+ マウス・キー入力が処理できなくてウィンドウがフリーズします。