|
すみません。昨日、投稿する時間を作れませんでした。
具体的に抜き出してみました。もちろん、適当に編集しています。
class ダイアログ : public CResizingDialog
{
public:
CObArray 結果リスト;
CWinThread* 通信スレッドハンドル[256];
int 通信中スレッド数;
//{{AFX_DATA(ダイアログ)
CListCtrl 通信状況リスト;
//}}AFX_DATA
}
void ダイアログ::ステータス設定(int インデックス, LPCTSTR ステータス)
{
// 処理中に通信状況をリアルタイム表示する
LV_ITEM item;
item.mask = LVIF_TEXT;
item.iItem = インデックス;
item.pszText = ステータス;
通信状況リスト.SetItem(&item);
通信状況リスト.Update(インデックス);
}
void ダイアログ::メッセージマップされた関数()
{
// 通信スレッドを作って、
int スレッド数 = 0;
for (int index = 0; index < 通信状況リスト.GetCount(); index++) {
if (通信相手リスト[index].通信するか == TRUE) {
通信スレッドハンドル[スレッド数++] = 通信スレッド開始処理(this, index);
}
}
// 終わるのを待ち、
while (通信中スレッド数 != 0) {
Sleep(1000);
メッセージ処理(); // Peek して Translate して Dispatch
}
// 結果を表示する。
通信結果を別のウインドウに引き渡す処理();
CResizingDialog::OnOK();
}
void ダイアログ::通信スレッド開始処理(ダイアログ* 元ウインドウ, int index)
{
通信スレッドClass *戻り値; // クラスの詳細省略
戻り値 = AfxBeginThread(RUNTIME_CLASS(通信スレッドClass), ...);
戻り値->ウインドウ = 元ウインドウ;
戻り値->インデックス = index;
通信中スレッド数++;
return 戻り値;
}
〜〜〜〜〜〜〜〜〜〜
class 通信スレッド : public CWinThread
{
public:
ダイアログ* ウインドウ;
int インデックス; // ListView 上のインデックス
/* その他、通信のためのデータ */
}
int 通信スレッド::Run()
{
/* UDP で送って、返信を待つ */
/* タイムアウトなどの振り分け処理の後、 */
// ★★これっていいのかヨ!!★★
this->ウインドウ->ステータス設定(this->インデックス, ステータス);
this->ウインドウ->結果リスト.Add(ステータス);
this->ウインドウ->通信中スレッド数--;
::PostQuitMessage(0);
return CWinThread::Run(); // これもいるのかョ??
}
〜〜〜〜〜〜〜〜〜〜
私が危ないと思うのは、class 通信スレッド での、
this->ウインドウ->ステータス設定(this->インデックス, ステータス);
this->ウインドウ->結果リスト.Add(ステータス);
this->ウインドウ->通信中スレッド数--;
の、3行です。
とりあえず、結果リスト、通信中スレッド数については public 公開をやめ、
操作のためのメソッドを追加し、CCriticalSection と CSingleLock でロックしました。
シャノンさんが引いてくださっているところを見ると、ステータス設定() でも、何らかの対策が必要?
ああ、もう。泣きたい。
|