今勉強中の初心者の者です。
Visual Studio2005(MFC)でダイアログベースのスレッドを使ったfile copyのプログラム
を作成しています。
サイズの大きなファイルをcopyしながらプログラスバーを更新していきます。
スレッドを起動してcopyのプログラムを実行します。そしてコピー状況をプログレスバ
ーに表示するプログラムです。
基本的なプログラムの動作は問題なく、コピー状況にあわせてプログレスバーが更新さ
れますが、
メッセージが処理できないようです。途中でwindowを移動したり、最小化することがで
きません。なぜでしょうか?
void CnewoneDlg:: copyfile()
{
//省略
while(k > 0){256バイトづつコピーループ
ReadFile (hf1, buff, sizeof(buff), &nRead, NULL);
WriteFile(hf2, buff, nRead, &nWriten, NULL) ;
// k、counter 変数の更新計算
}
//hf1, hf2クローズ、スレッド終了処理。
}
UINT CnewoneDlg::CopyThread( LPVOID pParam )
{ //threadからcopyプログラムを呼び出し
// copyfile()の呼び出し
}
void CnewoneDlg::OnBnClickedButton1()
{//ボタンコマンド
// スレッド開始
m_pCopythread = AfxBeginThread( CopyThread, this );//
LPMSG Msg = NULL;
while(mProgress.SetPos(counter) <100){ //100% コピーするまで
if(PeekMessage(Msg,NULL,0,0,PM_REMOVE) != 0)
DispatchMessage(Msg);
}//
}
while(mProgress.SetPos(counter) <100){ //100% コピーするまで
if(PeekMessage(Msg,NULL,0,0,PM_REMOVE) != 0)
DispatchMessage(Msg);
}//
ここが問題で、消して良い。
ここでわざわざメッセージループする必要は無いし、ループの仕方も間違ってい
る。
メッセージループはMFCが用意しているし、アクセラレータ用の処理もあるから特
に必要が無ければ自分では書かないほうが良い。
そして、PeekMessageをSleepその他無しで回したら、CPU負荷が100%になって
ファイルコピースレッドにも悪影響が出る。
ついでに、「LPMSG Msg = NULL;」は駄目。
PeekMessageは構造体を確保してくれるAPIではないし、もしそうなら引数は
LPMSGへのポインタになる。
PeekMessageは構造体は自分で用意する必要があります。
そして、「while(mProgress.SetPos(counter) <100)」はスレッドを分けた意味
を完全に無くしています。
正しく動作させたいなら、
void CnewoneDlg:: copyfile(){//省略
while(k > 0){
ReadFile (hf1, buff, sizeof(buff), &nRead, NULL);
WriteFile(hf2, buff, nRead, &nWriten, NULL) ;
// k、counter 変数の更新計算
}//hf1, hf2クローズ、スレッド終了処理。
}
void CnewoneDlg::OnBnClickedButton1(){
m_pCopythread = AfxBeginThread( CopyThread, this );
}
while(mProgress.SetPos(counter) <100){ //100% コピーするまで
if(PeekMessage(Msg,NULL,0,0,PM_REMOVE) != 0)
DispatchMessage(Msg);
}//
ここが問題で、消して良い。
ここでわざわざメッセージループする必要は無いし、ループの仕方も間違ってい
る。
メッセージループはMFCが用意しているし、アクセラレータ用の処理もあるから特
に必要が無ければ自分では書かないほうが良い。
そして、PeekMessageをSleepその他無しで回したら、CPU負荷が100%になって
ファイルコピースレッドにも悪影響が出る。
ついでに、「LPMSG Msg = NULL;」は駄目。
PeekMessageは構造体を確保してくれるAPIではないし、もしそうなら引数は
LPMSGへのポインタになる。
PeekMessageは構造体は自分で用意する必要があります。
そして、「while(mProgress.SetPos(counter) <100)」はスレッドを分けた意味
を完全に無くしています。
正しく動作させたいなら、
void CnewoneDlg:: copyfile(){//省略
while(k > 0){
ReadFile (hf1, buff, sizeof(buff), &nRead, NULL);
WriteFile(hf2, buff, nRead, &nWriten, NULL) ;
// k、counter 変数の更新計算
}//hf1, hf2クローズ、スレッド終了処理。
}
void CnewoneDlg::OnBnClickedButton1(){
m_pCopythread = AfxBeginThread( CopyThread, this );
}
投稿失敗。
正しく動作させたいなら、
void CnewoneDlg:: copyfile(){//省略
while(k > 0){
ReadFile (hf1, buff, sizeof(buff), &nRead, NULL);
WriteFile(hf2, buff, nRead, &nWriten, NULL) ;
// k、counter 変数の更新計算
mProgress.SetPos(counter);
}//hf1, hf2クローズ
//スレッド終了処理。
}
void CnewoneDlg::OnBnClickedButton1(){
m_pCopythread = AfxBeginThread( CopyThread, this );
//ボタン連打を回避する場合はm_pCopythreadが有効か調べた上でスレッ
ドを開始して、ボタンを無効にする。
}
投稿失敗。
正しく動作させたいなら、
void CnewoneDlg:: copyfile(){//省略
while(k > 0){
ReadFile (hf1, buff, sizeof(buff), &nRead, NULL);
WriteFile(hf2, buff, nRead, &nWriten, NULL) ;
// k、counter 変数の更新計算
mProgress.SetPos(counter);
}//hf1, hf2クローズ
//スレッド終了処理。
}
void CnewoneDlg::OnBnClickedButton1(){
m_pCopythread = AfxBeginThread( CopyThread, this );
//ボタン連打を回避する場合はm_pCopythreadが有効か調べた上でスレッ
ドを開始して、ボタンを無効にする。
}
いろいろありがとうございます。
うまくいきました。
まだまだスレッドの使い方が慣れていないようですね。
・・・・・
if(PeekMessage(Msg,NULL,0,0,PM_REMOVE) != 0)
DispatchMessage(Msg);
この部分は最初はなくて、うまくいかなくて付け加えていましたが、
更に深みにはまっていたわけですね。
・・・・
スレッドに対する本がAPIに関する本しかなかったので、直してる間にいつの間にかこう
なってしまったようです。