ワーカースレッドでヒープが壊れる – プログラミング – Home

ワーカースレッドでヒープが壊れる
 
通知
すべてクリア

[解決済] ワーカースレッドでヒープが壊れる


ツァラトゥストラ
 ツァラトゥストラ
(@ツァラトゥストラ)
ゲスト
結合: 13年前
投稿: 3
Topic starter  

よろしくお願いします。
開発環境: Windows 7 32 bit
VS2010 MFC MDI
行いたい処理
・MDI フレームメニューへイベントハンドラを追加し、そのイベントハンドラでモードレ
スダイアログを起動。
・モードレスダイアログへ追加した、開始ボタン押下でワーカースレッド起動。
・ワーカースレッドでは、ドキュメントクラス。及び、関連クラスを用いて、ファイルを
読込み、読み込んだ
ファイルのデータを元に約2000ファイルのダウンロード処理を行う。
・ファイル読込みの進捗を、モードレスダイアログのプログレスバーで表示。
このような処理を行いたいのですが、ワーカースレッドで呼ばれたメソッドから、同じド
キュメントクラスの
ダウンロードメソッドを呼ぶと、ヒープエリアが壊れてしまい、メモリエラーが発生しま

スレッド処理の考え方が間違っているのか?実装が間違っているのか?
または、その両方間違っているのか、判断がつきません、ご教示願います。

/*----------------------------------------------------------------------------*/
// DownloadWorkerthred()
/*----------------------------------------------------------------------------*/
/**
* @brief CDownLoadDialogクラスのワーカースレッドから呼ばれて行われる処理
* ダウンロードを行い、パラメータを用い適宜対応するファイル処理を行う
*/
/*----------------------------------------------------------------------------*/
void CxxxDoc::DownloadWorkerthred( PVOID pPara )
{
UINT dlmethod;
CDownLoadDialog* dlg = (CxxxDialog*)pPara;
dlmethod = dlg->GetRadioButton();

FileAccess fa;
std::map<std::string, std::string> mCode;
std::map<std::string, std::string>::iterator it;
fa.readFile();
mCode = fa.getCodeMap();

it=mCode.begin();
while( it != mCode.end() ) {
Download( it->first ); //! この処理を呼ぶと、ヒープが壊れる
it++;
}
}

追記:当該ダウンロード処理は、通常の処理(ワーカースレッドとして呼ばれない場合)
は、正常に動作します。


引用未解決
トピックタグ
ツァラトゥストラ
 ツァラトゥストラ
(@ツァラトゥストラ)
ゲスト
結合: 13年前
投稿: 3
Topic starter  

お世話になります。
MSDN のこのサイトを読みますと。
マルチスレッド : ワーカー スレッドの生成
http://msdn.microsoft.com/ja-jp/library/69644x60(v=vs.80).aspx
参考に下記のように実装しますと、制御するドキュメントクラスのハンドルが取得できて
いないようです
どうしたらいいでしょうか。

UINT MyThreadProc( LPVOID pParam )
{
CxxxDoc* pDoc = CxxxDoc::GetDoc();
if (pDoc == NULL ||
!pDoc->IsKindOf(RUNTIME_CLASS(CxxxDoc)))
return 1; // if pObject is not valid

CxxxDoc *pDoc = (CxxxDoc *)pParam;

pDoc->DownloadWorkerthred(pParam);

return 0;
}

/*----------------------------------------------------------------------------*/
// GetDoc()
/*----------------------------------------------------------------------------*/
/**
* @brief 現在の CDocument または CView からの任意の場所を取得するするに
は、方法
* http://support.microsoft.com/kb/108587/ja
*/
/*----------------------------------------------------------------------------*/
CxxxDoc * CxxxDoc::GetDoc()
{
CMDIChildWnd * pChild =
((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();

if ( !pChild )
return NULL; // CxxxDoc::GetDoc();ここでNULLを戻
してしまう。

CDocument * pDoc = pChild->GetActiveDocument();

if ( !pDoc )
return NULL;

// Fail if doc is of wrong kind
if ( ! pDoc->IsKindOf( RUNTIME_CLASS( CxxxDoc ) ) )
return NULL;

return (CxxxDoc *) pDoc;
}


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

CWnd (およびその派生クラス) は、同一インスタンスを異なるスレッドで使っては
ならないという制約があるので
http://support.microsoft.com/kb/147578/ja

CxxxDoc::GetDoc() は UI スレッド以外から使ってはいけない、のだろう。

どうすればよいか、は
どうしたいか、次第。

まあ普通は、ワーカースレッドからダイアログの HWND に対して (CWnd でなく)
メッセージを送る (PostMessage がよいか SendMessage が良いかは要検討)
ということになるのかな


返信引用
ツァラトゥストラ
 ツァラトゥストラ
(@ツァラトゥストラ)
ゲスト
結合: 13年前
投稿: 3
Topic starter  

tetrapod さん。ありがとうございます。
>CWnd (およびその派生クラス) は、同一インスタンスを異なるスレッドで使っては
>ならないという制約があるので
仕様ということで理解しました。
当方で、ドキュメントクラスをインスタンス化すると、余りに挙動がおかしいので
当該ドキュメントクラスで利用したかった、メッソッドを別クラスにて作成し、スレッド

してみたところ、いとも簡単に動作しましたので、その方法をとることとしました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました