質問編集履歴
14
タイトルをさらに修正
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
メインスレッドのコントロールを参照しているサブスレッドが
|
1
|
+
メインスレッドのコントロールを参照しているサブスレッドがアプリケーション終了時にコントロールの値の参照を正常に行えない[マルチスレッド][C++/MFC]
|
test
CHANGED
File without changes
|
13
タイトルを変えた旨記述
test
CHANGED
File without changes
|
test
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
タイトルをより適切に変更しました
|
2
|
+
|
1
3
|
###前提・実現したいこと
|
2
4
|
|
3
5
|
MFCアプリケーションを閉じる動作を行う際、コントロールが参照不能になる前に処理を行いたい。
|
12
やりたいこととタイトルが食い違っている気がしたのでタイトルやもろもろを変更。コードも最新版に合わせて変更
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
[マルチスレッド][C++/MFC]
|
1
|
+
メインスレッドのコントロールを参照しているサブスレッドがメインスレッド終了時に参照を正常に行えない[マルチスレッド][C++/MFC]
|
test
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
MFCアプリケーションを閉じる動作を行う際、コントロールが参照不能になる前に処理を行いたい。
|
4
4
|
|
5
|
-
閉じる動作を行う際にコントロールが参照不能になる以前の状態で処理を行えるイベントが知りたい。
|
5
|
+
~~ 閉じる動作を行う際にコントロールが参照不能になる以前の状態で処理を行えるイベントが知りたい。~~
|
6
|
+
|
7
|
+
閉じる動作を行う際にコントロールが参照不能になる現象を解消、または回避したい。
|
6
8
|
|
7
9
|
|
8
10
|
|
@@ -108,21 +110,27 @@
|
|
108
110
|
|
109
111
|
// メインループ(の代わりのWhileループ)
|
110
112
|
|
111
|
-
while( !this->m_exitAnotherThd); // m_exitAnotherThd == falseになるまで待機
|
112
|
-
|
113
113
|
int i =0;
|
114
114
|
|
115
|
-
i
|
115
|
+
while( !this->m_exitAnotherThd){ // m_exitAnotherThd == falseになるまで待機
|
116
116
|
|
117
|
-
//
|
117
|
+
// ここから先に進まない
|
118
118
|
|
119
|
+
i = ((CSliderCtrl *)FromHanlde(this->m_hwnd)->GetDlgItem(IDC_SLIDER1))->GetPos(); // ウィンドウハンドラを介して取得
|
119
120
|
|
121
|
+
}
|
122
|
+
|
123
|
+
i = ((CSliderCtrl *)FromHanlde(this->m_hwnd)->GetDlgItem(IDC_SLIDER1))->GetPos();
|
124
|
+
|
125
|
+
// i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos();
|
120
126
|
|
121
127
|
return S_OK;
|
122
128
|
|
123
129
|
}
|
124
130
|
|
125
131
|
```
|
132
|
+
|
133
|
+
- OnDestory()関数が呼び出されるまではiにスライダの値が正常に入ります。
|
126
134
|
|
127
135
|
以上のコードは実際に実装しているものとは異なります。雰囲気だけでも伝われば幸いです。
|
128
136
|
|
11
さらに値の取得方法を変更
test
CHANGED
File without changes
|
test
CHANGED
@@ -112,7 +112,7 @@
|
|
112
112
|
|
113
113
|
int i =0;
|
114
114
|
|
115
|
-
i = ((CSliderCtrl *)FromHanlde(this->m_hnd
|
115
|
+
i = ((CSliderCtrl *)FromHanlde(this->m_hwnd)->GetDlgItem(IDC_SLIDER1))->GetPos(); // ウィンドウハンドラを介して取得
|
116
116
|
|
117
117
|
// i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos(); // ここから先に進まない
|
118
118
|
|
10
x Fromhandle o FromHandle
test
CHANGED
File without changes
|
test
CHANGED
@@ -112,7 +112,7 @@
|
|
112
112
|
|
113
113
|
int i =0;
|
114
114
|
|
115
|
-
i = ((CSliderCtrl *)From
|
115
|
+
i = ((CSliderCtrl *)FromHanlde(this->m_hndl))->GetPos(); // m_hndlはOnInitDialog()内でm_hndl = GetDlgItem(IDC_SLIDER1)->GetSafeHwnd()してあります。
|
116
116
|
|
117
117
|
// i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos(); // ここから先に進まない
|
118
118
|
|
9
ハンドラ経由の取得方法?に変更
test
CHANGED
File without changes
|
test
CHANGED
@@ -112,7 +112,9 @@
|
|
112
112
|
|
113
113
|
int i =0;
|
114
114
|
|
115
|
+
i = ((CSliderCtrl *)Fromhanlde(this->m_hndl))->GetPos(); // m_hndlはOnInitDialog()内でm_hndl = GetDlgItem(IDC_SLIDER1)->GetSafeHwnd()してあります。
|
116
|
+
|
115
|
-
i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos(); // ここから先に進まない
|
117
|
+
// i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos(); // ここから先に進まない
|
116
118
|
|
117
119
|
|
118
120
|
|
8
インデントを修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -70,13 +70,13 @@
|
|
70
70
|
|
71
71
|
if( !GetExitCodeThread( this->m_hAnotherThread, &exitCode))
|
72
72
|
|
73
|
-
|
73
|
+
{
|
74
74
|
|
75
|
-
|
75
|
+
TerminateThread( this->m_hAnotherThread, E_FAIL);
|
76
76
|
|
77
|
-
|
77
|
+
break;
|
78
78
|
|
79
|
-
|
79
|
+
}
|
80
80
|
|
81
81
|
}while( exitCode == STILL_ACTIVE);
|
82
82
|
|
7
いろいろ直しました
test
CHANGED
File without changes
|
test
CHANGED
@@ -16,9 +16,9 @@
|
|
16
16
|
|
17
17
|
- メインスレッドではGetExitCodeThread()を実行する前に別スレッドのループを終わらせるフラグを立てて、別スレッドが終了したときにGetExitCodeThread()でexitCode = 0 となるようにしいます。
|
18
18
|
|
19
|
-
-
|
19
|
+
- OnDestroy()を使用しているのはブレークポイントを設置して観察して、OnClose()や~CMyAppDlg()よりも早く実行されることを確認したためです。
|
20
20
|
|
21
|
-
|
21
|
+
|
22
22
|
|
23
23
|
実際のソースコードを提示できないため抽象的な質問になり申し訳ありませんが、アドバイスなど頂けたら幸いです。
|
24
24
|
|
@@ -40,13 +40,15 @@
|
|
40
40
|
|
41
41
|
###該当のソースコード
|
42
42
|
|
43
|
-
[このサイト](http://keicode.com/winprimer/wp15.php)などを参照するとOnDestroy()より先にOnClose()が走るようなので修正しました。
|
43
|
+
~~[このサイト](http://keicode.com/winprimer/wp15.php)などを参照するとOnDestroy()より先にOnClose()が走るようなので修正しました。~~
|
44
|
+
|
45
|
+
OnDestroy内に記述でもよいとのご指摘があったので元に戻し、ご指摘のあった部分を修正しました。
|
44
46
|
|
45
47
|
|
46
48
|
|
47
49
|
```c++
|
48
50
|
|
49
|
-
void CMyAppDlg::On
|
51
|
+
void CMyAppDlg::OnDestroy()
|
50
52
|
|
51
53
|
{
|
52
54
|
|
@@ -66,13 +68,17 @@
|
|
66
68
|
|
67
69
|
// this->m_hAnotherThread は ResumeThread( this->m_hAnotherThread);によって開始済みのスレッド
|
68
70
|
|
69
|
-
|
71
|
+
if( !GetExitCodeThread( this->m_hAnotherThread, &exitCode))
|
70
72
|
|
71
|
-
|
73
|
+
{
|
72
74
|
|
73
|
-
|
75
|
+
TerminateThread( this->m_hAnotherThread, E_FAIL);
|
74
76
|
|
77
|
+
break;
|
78
|
+
|
79
|
+
}
|
80
|
+
|
75
|
-
}while( exitCode
|
81
|
+
}while( exitCode == STILL_ACTIVE);
|
76
82
|
|
77
83
|
// mutex
|
78
84
|
|
@@ -80,11 +86,37 @@
|
|
80
86
|
|
81
87
|
|
82
88
|
|
83
|
-
CDialog::On
|
89
|
+
CDialog::OnDestroy();
|
84
90
|
|
85
91
|
|
86
92
|
|
87
93
|
// TODO: ここにメッセージ ハンドラ コードを追加します。
|
94
|
+
|
95
|
+
}
|
96
|
+
|
97
|
+
// 別スレッドの実行内容
|
98
|
+
|
99
|
+
DWORD WINAPI CMyAppDlg::ExecThread()
|
100
|
+
|
101
|
+
{
|
102
|
+
|
103
|
+
WaitForSingleObject( this->m_mutex, 0);
|
104
|
+
|
105
|
+
this->m_exitAnotherThd = false; // ループ終了フラグ
|
106
|
+
|
107
|
+
ReleaseMutex( this->m_mutex);
|
108
|
+
|
109
|
+
// メインループ(の代わりのWhileループ)
|
110
|
+
|
111
|
+
while( !this->m_exitAnotherThd); // m_exitAnotherThd == falseになるまで待機
|
112
|
+
|
113
|
+
int i =0;
|
114
|
+
|
115
|
+
i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos(); // ここから先に進まない
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
return S_OK;
|
88
120
|
|
89
121
|
}
|
90
122
|
|
6
間違っていた部分を修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -16,9 +16,9 @@
|
|
16
16
|
|
17
17
|
- メインスレッドではGetExitCodeThread()を実行する前に別スレッドのループを終わらせるフラグを立てて、別スレッドが終了したときにGetExitCodeThread()でexitCode = 0 となるようにしいます。
|
18
18
|
|
19
|
-
- OnDestroy()を使用しているのはブレークポイントを設置して観察して、OnClose()や~CMyAppDlg()よりも早く実行されることを確認したためです。
|
19
|
+
- ~~OnDestroy()を使用しているのはブレークポイントを設置して観察して、OnClose()や~CMyAppDlg()よりも早く実行されることを確認したためです。
|
20
20
|
|
21
|
-
|
21
|
+
~~
|
22
22
|
|
23
23
|
実際のソースコードを提示できないため抽象的な質問になり申し訳ありませんが、アドバイスなど頂けたら幸いです。
|
24
24
|
|
@@ -40,9 +40,13 @@
|
|
40
40
|
|
41
41
|
###該当のソースコード
|
42
42
|
|
43
|
+
[このサイト](http://keicode.com/winprimer/wp15.php)などを参照するとOnDestroy()より先にOnClose()が走るようなので修正しました。
|
44
|
+
|
45
|
+
|
46
|
+
|
43
47
|
```c++
|
44
48
|
|
45
|
-
void CMyAppDlg::On
|
49
|
+
void CMyAppDlg::OnClose()
|
46
50
|
|
47
51
|
{
|
48
52
|
|
@@ -76,7 +80,7 @@
|
|
76
80
|
|
77
81
|
|
78
82
|
|
79
|
-
CDialog::On
|
83
|
+
CDialog::OnClose();
|
80
84
|
|
81
85
|
|
82
86
|
|
5
タグのつけ忘れ
test
CHANGED
File without changes
|
test
CHANGED
File without changes
|
4
文章を改善
test
CHANGED
File without changes
|
test
CHANGED
@@ -8,15 +8,15 @@
|
|
8
8
|
|
9
9
|
- 作成中のアプリケーションはダイアログベースのMFCアプリケーションです。
|
10
10
|
|
11
|
-
- OnDestroy()イベント関数内で、CDialog::OnDestroy()が走る前にGetExitCodeThread()で別スレッドの終了コードを取得して別スレッドの終了を確認してから
|
11
|
+
- OnDestroy()イベント関数内で、CDialog::OnDestroy()が走る前にGetExitCodeThread()で別スレッドの終了コードを取得して別スレッドの終了を確認してからアプリケーションを終了する処理を実装しようとしています。
|
12
12
|
|
13
13
|
- 別スレッドは1つです。
|
14
14
|
|
15
15
|
- 別スレッド内ではループで処理を行い、その中ではメインスレッドのコントロールの値を参照しています。
|
16
16
|
|
17
|
-
- メインスレッドではGetExitCodeThread()を実行する前に別スレッドのループを終わらせるフラグを立てて、別スレッドが終了したときにGetExitCodeThread
|
17
|
+
- メインスレッドではGetExitCodeThread()を実行する前に別スレッドのループを終わらせるフラグを立てて、別スレッドが終了したときにGetExitCodeThread()でexitCode = 0 となるようにしいます。
|
18
18
|
|
19
|
-
- OnDestroy()を使用しているのはブレークポイントを設置して観察して、OnClose()
|
19
|
+
- OnDestroy()を使用しているのはブレークポイントを設置して観察して、OnClose()や~CMyAppDlg()よりも早く実行されることを確認したためです。
|
20
20
|
|
21
21
|
|
22
22
|
|
@@ -28,13 +28,13 @@
|
|
28
28
|
|
29
29
|
###発生している問題・エラーメッセージ
|
30
30
|
|
31
|
-
OnDestory()に処理が移って別スレッドの終了
|
31
|
+
OnDestory()に処理が移って別スレッドのループ終了フラグがtrueになったあと
|
32
32
|
|
33
|
-
別スレッドが最後のループに入ったときに、スライドコントロールの
|
33
|
+
別スレッドが最後のループに入ったときに、スライドコントロールの位置を参照しようと( CSliderCtrl::GetPos() )すると
|
34
34
|
|
35
|
-
エラーメッセージが出るわけでも突然プロセスが終了するわけでもなく、GetExitCodeThread()の値を監視しているループから抜けられ
|
35
|
+
エラーメッセージが出るわけでも突然プロセスが終了するわけでもなく、GetExitCodeThread()の値を監視しているループから抜けられずアプリケーションが終了しなくなってしまいます。
|
36
36
|
|
37
|
-
別スレッドでは
|
37
|
+
別スレッドではCSliderCtrl::GetPos()の処理に入ってから処理が進まなくなります。
|
38
38
|
|
39
39
|
|
40
40
|
|
3
質問内容を少し改善
test
CHANGED
File without changes
|
test
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
###前提・実現したいこと
|
2
2
|
|
3
3
|
MFCアプリケーションを閉じる動作を行う際、コントロールが参照不能になる前に処理を行いたい。
|
4
|
+
|
5
|
+
閉じる動作を行う際にコントロールが参照不能になる以前の状態で処理を行えるイベントが知りたい。
|
4
6
|
|
5
7
|
|
6
8
|
|
2
指摘を受けてコードを一部改善
test
CHANGED
File without changes
|
test
CHANGED
@@ -60,7 +60,11 @@
|
|
60
60
|
|
61
61
|
// this->m_hAnotherThread は ResumeThread( this->m_hAnotherThread);によって開始済みのスレッド
|
62
62
|
|
63
|
-
GetExitCodeThread( this->m_hAnotherThread, &exitCode);
|
63
|
+
bool b = GetExitCodeThread( this->m_hAnotherThread, &exitCode);
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
if(!b)TerminateThread( this->m_hAnotherThread, E_FAIL);
|
64
68
|
|
65
69
|
}while( exitCode != S_OK);
|
66
70
|
|
1
不足していた情報を追加
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
[C++/MFC]MFCアプリケーションを閉じる動作を行う際、コントロールが参照不能になる前に処理を行いたい。
|
1
|
+
[マルチスレッド][C++/MFC]MFCアプリケーションを閉じる動作を行う際、コントロールが参照不能になる前に処理を行いたい。
|
test
CHANGED
File without changes
|