Windows XPとVC++ 6.0で
時間のかかる大量の計算をするプログラムを作っています。
計算部分はスレッド処理にして
進捗ダイアログ(CDialogにCProgressCtrlを貼り付けたもの)
を表示します。
・CWinAppのInitInstanceで計算処理開始(AfxBeginThread)
・計算処理内で進捗ダイアログをCreate
・計算の進み具合によって進捗ダイアログのプログレスバーを更新
上記の流れではうまくいっていたのですが
以下のように変更したところ、進捗ダイアログをCreateするところで
プログラムが応答なしになってしまうようになりました。
・メインダイアログ(モーダル)
・メインダイアログのAボタンクリックでダイアログAを開く(モーダル)
・ダイアログAの実行ボタンクリックで計算処理開始(AfxBeginThread)
・計算処理内で進捗ダイアログをCreate
・計算の進み具合によって進捗ダイアログのプログレスバーを更新
MFC Wizardでダイアログベースで作成、MFCの共有DLLを使用しています。
モーダルダイアログ→スレッド→CDialog.Createに
制限があったりするのでしょうか。
どうかご教授ください。
No.4ベストアンサー
- 回答日時:
スレッドを作成した側の待機処理ループの中にメッセージポンプを作成してやればよさそうですよ
pThread->ResumeThread();
do {
AfxGetApp()->PumpMessage();
} while( WaitForSingleObject( pThread->m_hThread, 0 ) != WAIT_OBJECT_0 );
といった具合で …
メインスレッド寝てしまっているので反応無しになるのかも
No.3
- 回答日時:
AttachThreadInputは根本的な解決になっていないようです
新規に MFCダイアログベースで起こしたプロジェクトで
1) モーダルダイアログを追加
2) このダイアログのボタンでワーカースレッドを起動
3) スレッド制御関数の中でプログレスバーダイアログを作成
といった具合にしてみましたが すんなり動いてしまいました
CProgressBarDlg dlg;
dlg.Create( リソースID, NULL );
であればすんなり動くようです
親ウィンドウのポインタを渡してしまうとアサーションが起きます
最終的には CDialog::CreateIndirectで AfxGetMainWnd()で親を探しているので同じようにスレッド制御関数でAfxGetMainWnd()を取得して渡してもアサーションです
一番最初にコーディングした際は 確かにダンマリモードになったんですが2回目以降ダンマリモードの状態が再現できない状態です
この回答への補足
#前回の投稿箇所を誤ってしまったようです。
↓の次の投稿になります。申し訳ありません。
> redfox63さん、ご回答ありがとうございます。
> 当方の環境はWindows XP SP2 + VC++ 6.0 SP6です。
> VC++ 6.0 SP5の環境を作って試してみたのですが
> やはり応答なしになってしまいました。
- - - - - - - - - - - - - - - - - - - - - - - - -
すみません、自己解決です。(というか諦め…)
スレッドの中でCProgrerss.Createを行わずに
呼び出し側のダイアログ(の実行ボタン)で
進捗ダイアログを作ることにしました。
BOOL CMainDlg::OnRun()
{
...
CProgressDlg dlg;
dlg.Create(IDD_PROGRESSDLG, this);
dlg.ShowWindow(SW_SHOW);
CALC_PARAMDATA ParamData;
CWinThread* pThread = NULL;
ParamData.i1 = n1;
ParamData.i2 = n2;
ParamData.pWnd = this;
pThread = AfxBeginThread(::CalcThreadFunc, &Param, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pThread->m_bAutoDelete = FALSE;
pThread->ResumeThread();
do
{
// 進捗の度合い(グローバル変数)によって
// CProgressのプログレスバーを進める
// 進捗の度合いはスレッド内で更新
}
while(WaitForSingleObject(pThread->m_hThread, 0) !=WAIT_OBJECT_0);
delete pThread;
...
}
首記の「スレッドからダイアログを表示」については
まだ腑に落ちない点がありますが、
下記のサイトで
「MFCでは、スレッドまたいでの、CWndオブジェクトのポインタによるウインドウ操作は保証されていません」
と発言している方がいらっしゃいました。
http://homepage1.nifty.com/MADIA/vc/vc_bbs/20050 …
ちょっとMSDNを確認しようと思います。
redfox63さん、たくさんお時間を割いていただきまして恐縮です。
ありがとうございました。
redfox63さん、ご回答ありがとうございます。
当方の環境はWindows XP SP2 + VC++ 6.0 SP6です。
VC++ 6.0 SP5の環境を作って試してみたのですが
やはり応答なしになってしまいました。
ソースは以下のようになっています。
※最初の質問ではモーダルダイアログが2つありましたが
単純にするため1つにしました。その他諸々簡略化してあります。
※モーダル1つでも当方では同じ現象になります。
*MainApp.h
int CalcFunc(int i1, int i2);
typedef struct _CALC_PARAMDATA
{
int i1;
int i2;
CWnd* pWnd;
int ret;
} CALC_PARAMDATA ,*PCALC_PARAMDATA;
class CMainApp : public CWinApp
{
...
}
UINT CalcThreadProc(LPVOID pParam);
*MainApp.cpp
BOOL CMainApp::InitInstance()
{
...
CMainDlg dlg;
dlg.DoModal();
...
}
UINT CalcThreadProc(LPVOID pParam)
{
int i1 = ((PCALC_PARAMDATA)pParam)->i1;
int i2 = ((PCALC_PARAMDATA)pParam)->i2;
CWnd* pWnd = ((PCALC_PARAMDATA)pParam)->pWnd;
// ちなみに、ここでCProgressDlgをCreateしても
// 応答なしになります
int ret = CalcFunc(i1, i2, pWnd);
((PCALC_PARAMDATA)pParam)->ret = ret;
}
int CalcFunc(DWORD dw1, DWORD dw2, CWnd* pWnd)
{
CProgressDlg dlg;
dlg.Create(IDD_PROGRESSDLG, NULL);// またはpWnd
dlg.ShowWindow(SW_SHOW);
...
}
*MainDlg.cpp
BOOL CMainDlg::OnRun()
{
...
CALC_PARAMDATA ParamData;
CWinThread* pThread = NULL;
ParamData.i1 = n1;
ParamData.i2 = n2;
ParamData.pWnd = this;
pThread = AfxBeginThread(::CalcThreadFunc, &Param, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pThread->m_bAutoDelete = FALSE;
pThread->ResumeThread();
do
{
}
while(WaitForSingleObject(pThread->m_hThread, 0) !=WAIT_OBJECT_0);
delete pThread;
...
}
No.2
- 回答日時:
おかしいですね … 当方の環境ですと動作してしまっているのですが
WinXP SP2 + VC++6.0 SP5の環境です
AfxGetThreadを AfxGetAppに変更してみてはいかがでしょう
別の手段として プログレスダイアログは ダイアログAのボタンクリックイベント内で生成して
スレッドプロークの引数に プログレスダイアログのアドレス(ポインタ)を渡すとか
他に引き渡すデータがあるなら 構造体にしてそのメンバーにプログレスダイアログポインタを持たすなどしてはいかがでしょう
No.1
- 回答日時:
親ウィンドウを探しにいって迷子になっているのでしょう
ワーカースレッドの場合 AttachThreadInputなどでアプリケーションスレッドをアタッチしてやればいいようです
スレッドプロークの中で
CProgressDlg dlg;
AttachThreadInput( ::GetCurrentThreadId(), AfxGetThread()->m_nThreadID, True);
dlg.Create( IDD_PROGRESSDLG, NULL );
dlg.ShowWindow( SW_SHOW );
while( 1 ) {
if ( 終了条件 )
break;
// 何かの処理
}
AttachThreadInput( ::GetCurrentThreadId(), AfxGetThread()->m_nThreadID, FALSE);
dlg.DestroyWindow();
といった具合で
この回答への補足
redfox63さん、ご回答ありがとうございます。
しかしAttachThreadInputでも同様の結果になってしまいました。。
GetCurrentThreadIdで取得した呼び出し側スレッドのIDと
AfxGetThreadで取得した現在実行中のスレッドのIDが
同じ値になっているのですが、そのことと何か関係がありますでしょうか。
また、「親ウィンドウを探しにいって迷子になっているのでしょう」をヒントに
Createの第二引数に親ウィンドウのハンドルを渡してみたのですが
そうするとDebugモードでは、Createの箇所でDebug Assertion Failedになってしまいます。
(wincore.cppの883行目)
hWndがウィンドウかどうかの判定で「ウィンドウでない」と見なされるようです。
CProgressDlg dlg;
AttachThreadInput(::GetCurrentThreadId(), AfxGetThread()->m_nThreadID, TRUE);
dlg.Create(IDD_PROGRESSDLG, hWnd);// ここで応答なし またはDebug Assertion Failed
dlg.ShowWindow(SW_SHOW);
...
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(教育・科学・学問) 進捗率の計算方法を教えてください。 90日の売上目標500万 20日経過時点で100万。 予定の進捗 1 2022/08/22 12:10
- その他(ソフトウェア) UnityのPublishing SettingsでCreate Keyを押しても反応しない 1 2023/06/27 01:03
- 計算機科学 進捗率の計算方法がわかりません! 全件数:86件 完了予定:71 完了数50 何%になるのか、計算方 3 2022/10/31 15:18
- C言語・C++・C# Seleniumで「ファイルを開く」ダイアログボックスのフォルダ指定する方法を教えてください。 1 2022/05/09 07:38
- その他(Microsoft Office) Office(Windows版,Word/Excel/PowerPoint等)にログインできません 4 2022/07/24 15:18
- Visual Basic(VBA) VBA 参照先で選んだファイルをコピーし、出力先に別名で保存したい 8 2022/05/13 20:37
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- Visual Basic(VBA) エクセルのマクロについて教えてください。 7 2023/07/04 09:18
- Windows 10 MSアカウントの「個人設定をクラウドから削除します」は機能していないのでしょうか? 1 2022/11/20 17:01
- 情報処理技術者・Microsoft認定資格 応用情報処理技術者試験のシステム利用率の計算について 2 2022/03/28 07:43
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
65536は2の何乗なのでしょうか?
-
VBAの再計算が反映されない件に...
-
Visual C++でdebugとreleaseで...
-
排他的論理和 BCC(水平パリテ...
-
Javaでのある数の小数点乗に...
-
★PHP★平日、休日の区別はできま...
-
素数を自動的に作る
-
骨折リスク評価のFRAXについて...
-
C言語 log実装
-
VBAで関数をつくる
-
C言語初心者。静磁場の計算。台...
-
エクセルで特定のセルのみを任...
-
60進数の四則計算
-
傾いた四角形内の範囲の条件式
-
数値計算の高速化 (cos, sin, exp)
-
C言語で電卓を作成する。修正お...
-
関数電卓をc言語でつくりたいの...
-
変化させるセルが変化しない
-
prolog計算
-
CRC8を教えてください
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
65536は2の何乗なのでしょうか?
-
VBAの再計算が反映されない件に...
-
排他的論理和 BCC(水平パリテ...
-
EXCELなどで「返す」という表現
-
バッチファイルでウインドウを...
-
モジュラス103の計算とは何でし...
-
傾いた四角形内の範囲の条件式
-
Visual C++でdebugとreleaseで...
-
変化させるセルが変化しない
-
骨折リスク評価のFRAXについて...
-
C# 計算処理中に実行中ウィン...
-
VBAでの勤務時間計算
-
べき乗の計算が遅い理由
-
C言語についてです。 再帰を使...
-
Excel VBAにてFFT
-
数値計算の高速化 (cos, sin, exp)
-
VBとVBAの違い
-
VB6で正確なミリ秒を計測したい...
-
スレッド処理からダイアログを...
-
matlabで計算終了
おすすめ情報