回答編集履歴

3

間違ってそうな部分を削除

2017/05/31 05:16

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -32,6 +32,10 @@
32
32
 
33
33
 
34
34
 
35
+ ※調べなおしてたら勘違いな気がしてきたので括っておきます
36
+
37
+ ```
38
+
35
39
  で、ここからが本題です。
36
40
 
37
41
  **サブスレッドからウィンドウを作っても新しくメッセージループは作成されません。**
@@ -41,6 +45,8 @@
41
45
 
42
46
 
43
47
  別スレッドから画面を作成したとしても、Formの`DoModal`等の処理はメッセージループに依頼を投げた後、メッセージが処理されるのを待つことになります。下位のダイアログなどのクラスはそういった依頼を簡易化する処理だけで成り立っているはずです。このためにサブスレッドからウィンドウを表示しようとしても停止してしまいます。
48
+
49
+ ```
44
50
 
45
51
 
46
52
 
@@ -78,20 +84,6 @@
78
84
 
79
85
 
80
86
 
81
- ただ、正攻法としてはやはりサブスレッドに重たい処理を移行することです。
82
-
83
- どんなに重い処理をメインスレッドでやっていようとその処理を切り出してバックグラウンドプロセスに投げれない理由はそうそうないと思います。
84
-
85
- 新しくメッセージループを作って協調動作させるよりよっぽど低コストになるはずです。
86
-
87
-
88
-
89
- 内部で扱っているフォームのフィールド情報等を全て1個のオブジェクトに詰め、重たい処理の開始から終了までにかかわる部分を一つのメソッドにして非同期化し、そのあとにサブウィンドウを表示するようにしてください。
90
-
91
-
92
-
93
-
94
-
95
87
  #追記
96
88
 
97
89
  追記勘違いっぽかったので削除しました。

2

追記を削除

2017/05/31 05:16

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -94,80 +94,6 @@
94
94
 
95
95
  #追記
96
96
 
97
- と…思ましたが、ちょとgooglingしてら割と自前でピーク皆さんやっているようなので、別のスレッドで以下のようなことをやっていれば十分動くかもれないですね
97
+ 追記勘違いっぽかったので削除ました
98
98
 
99
-
100
-
101
- ```C++
102
-
103
- struct CancellationToken
99
+ やったことないことは回答に書いてはダメですね。
104
-
105
- {
106
-
107
- CancellationToken() : Cancel(false) {}
108
-
109
- bool Cancel;
110
-
111
- }
112
-
113
-
114
-
115
- UINT SubMessageLoop(LPVOID param)
116
-
117
- {
118
-
119
- CancellationToken *token = (*CancellationToken)param;
120
-
121
- MSG msg;
122
-
123
-
124
-
125
- while(!token->Cancel && GetMessage(&msg, NULL, 0, 0))
126
-
127
- {
128
-
129
- TranslateMessage(&msg);
130
-
131
- DispatchMessage(&msg);
132
-
133
- }
134
-
135
- }
136
-
137
- ```
138
-
139
- ---
140
-
141
-
142
-
143
- ```C++
144
-
145
- CancellationToken *token = new CancellationToken()
146
-
147
- CWinThread *sub_message_loop = AfxBeginThread(SubMessageLoop, token);
148
-
149
- AfxBeginThread(TestThreadProc, this);
150
-
151
-
152
-
153
- // 重たい処理を行う
154
-
155
- while (...)
156
-
157
- {
158
-
159
- }
160
-
161
-
162
-
163
- // 処理が終わったらサブのメッセージループを止める
164
-
165
- token->Cancel = true;
166
-
167
- WaitForSingleObject(sub_message_loop, INFINITE);
168
-
169
- ```
170
-
171
-
172
-
173
- ただ、直観的には動作が不安定になりそうな気もするので…`PeekMessage`使う方が自然かもですね。

1

追記

2017/05/31 04:42

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -87,3 +87,87 @@
87
87
 
88
88
 
89
89
  内部で扱っているフォームのフィールド情報等を全て1個のオブジェクトに詰め、重たい処理の開始から終了までにかかわる部分を一つのメソッドにして非同期化し、そのあとにサブウィンドウを表示するようにしてください。
90
+
91
+
92
+
93
+
94
+
95
+ #追記
96
+
97
+ と…思いましたが、ちょっとgooglingしてたら割と自前でピーク皆さんやっているようなので、別のスレッドで以下のようなことをやっていれば十分動くかもしれないですね。
98
+
99
+
100
+
101
+ ```C++
102
+
103
+ struct CancellationToken
104
+
105
+ {
106
+
107
+ CancellationToken() : Cancel(false) {}
108
+
109
+ bool Cancel;
110
+
111
+ }
112
+
113
+
114
+
115
+ UINT SubMessageLoop(LPVOID param)
116
+
117
+ {
118
+
119
+ CancellationToken *token = (*CancellationToken)param;
120
+
121
+ MSG msg;
122
+
123
+
124
+
125
+ while(!token->Cancel && GetMessage(&msg, NULL, 0, 0))
126
+
127
+ {
128
+
129
+ TranslateMessage(&msg);
130
+
131
+ DispatchMessage(&msg);
132
+
133
+ }
134
+
135
+ }
136
+
137
+ ```
138
+
139
+ ---
140
+
141
+
142
+
143
+ ```C++
144
+
145
+ CancellationToken *token = new CancellationToken()
146
+
147
+ CWinThread *sub_message_loop = AfxBeginThread(SubMessageLoop, token);
148
+
149
+ AfxBeginThread(TestThreadProc, this);
150
+
151
+
152
+
153
+ // 重たい処理を行う
154
+
155
+ while (...)
156
+
157
+ {
158
+
159
+ }
160
+
161
+
162
+
163
+ // 処理が終わったらサブのメッセージループを止める
164
+
165
+ token->Cancel = true;
166
+
167
+ WaitForSingleObject(sub_message_loop, INFINITE);
168
+
169
+ ```
170
+
171
+
172
+
173
+ ただ、直観的には動作が不安定になりそうな気もするので…`PeekMessage`使う方が自然かもですね。