_beginthreadex()で生成したスレッドを終了したらハンドルを閉じたくて以下のコードを
書きました
以下のコードはあるスレッドから一定間隔で呼ばれます
WaitForMultipleObjectsをFAlSEで使うのが初めてなんですが・・・
WaitForMultipleObjectsで判定しているループ内で1つづつスレッドをクローズできるつ
もりでコードを書きました
しかし、動かしてみると、1つクローズして、ループが回り、もう一度、
WaitForMultipleObjects()がよばれるとパラメーターエラーとなります
これはなぜでしょうか?
一度WaitForMultipleObjects()を呼び出したときに、シグナル状態だったスレッドのハン
ドルを持った配列をもう一度WaitForMultipleObjects()に渡してはいけないのでしょうか?
WaitForSingleObject()をスレッドの数分使用してハンドルのクローズを行うべきなんで
しょうか?
DWORD ret;
HANDLE *cur_point = m_aThreadHandles;//_begginthreadで生成したスレッドのハンドル
を持つ配列
for (int i = 0; i < m_nThreadCount/*生成したスレッドの数*/; i +=
MAXIMUM_WAIT_OBJECTS) {
int cur_cnt = min(m_nThreadCount - i, MAXIMUM_WAIT_OBJECTS);
while ((ret = WaitForMultipleObjects(cur_cnt, cur_point, FALSE, 1))
!= WAIT_TIMEOUT) {
if (ret == WAIT_FAILED) {
return EComEnvSystemError;
}
ret -= WAIT_OBJECT_0;
if (ret >= 0 && ret < cur_cnt) {
CloseHandle(cur_point[ret]);
memmove(cur_point + ret, cur_point + ret + 1,
sizeof(HANDLE) * (m_nThreadCount - i - ret - 1));
m_nThreadCount--;
}
cur_cnt = min(m_nThreadCount - i, MAXIMUM_WAIT_OBJECTS);
}
cur_point += MAXIMUM_WAIT_OBJECTS;
}
WinXP SP2 VC++6.0 SP5
一目見ただけでバグってますが
>しかし、動かしてみると、1つクローズして、ループが回り、もう一度、
>WaitForMultipleObjects()がよばれるとパラメーターエラーとなります
>これはなぜでしょうか?
デバッガで変数見てみれば?
>WaitForSingleObject()をスレッドの数分使用してハンドルのクローズを行うべきなんで
>しょうか?
MSを疑う前に自分のコードを疑いましょう
うーん、デバッガで追うまでもなく、おかしいですね。
御自分で言われている
「1つクローズして、ループが回り、もう一度、WaitForMultipleObjects()が
よばれるとパラメーターエラーとなります」
の所の流れをよく見てみて下さい。
明らかにおかしな事をしているのがわかるはずです。
WaitForSingleObject()/WaitForMultipleObjects()の使用目的は?
最後、スレッドが終了したかどうか確かめるだけなら、
最後にWaitForMultipleObjects()一回だけでいいんじゃないですか。
イベント等の同期をとる目的ならそれ相応に
WaitForSingleObject()とWaitForMultipleObjects()を使い分けなければ
いけないと思います。
すいません
記載したコードが間違っていました
二箇所で スレッドのカウントをいじってました
正しくは以下です
DWORD ret;
HANDLE *cur_point = m_aThreadHandles;
for (int i = 0; i < m_nThreadCount; i += MAXIMUM_WAIT_OBJECTS) {
// int cur_cnt = min(m_nThreadCount - i, MAXIMUM_WAIT_OBJECTS);
int cur_cnt = min(m_nThreadCount, MAXIMUM_WAIT_OBJECTS);
while ((ret = WaitForMultipleObjects(cur_cnt, cur_point, FALSE, 1))
!= WAIT_TIMEOUT) {
DWORD result = GetLastError();
if (ret == WAIT_FAILED) {
return EComEnvSystemError;
}
ret -= WAIT_OBJECT_0;
if (ret >= 0 && ret < cur_cnt) {
CloseHandle(cur_point[ret]);
memmove(cur_point + ret, cur_point + ret + 1,
sizeof(HANDLE) * (m_nThreadCount - i - ret - 1));
m_nThreadCount--;
}
// cur_cnt = min(m_nThreadCount - i, MAXIMUM_WAIT_OBJECTS);
cur_cnt = min(m_nThreadCount, MAXIMUM_WAIT_OBJECTS);
}
cur_point += MAXIMUM_WAIT_OBJECTS;
}
>WaitForSingleObject()/WaitForMultipleObjects()の使用目的は?
WaitForSingleObject()をスレッド数分まわしてシグナル状態のものだけクローズしても
良いかと思うのですが、WaitForMultipleObjects()でもいけるのかな?と
すいません
スレッドのカウントが間違っていて、WaitForMultipleObjects()の第一引数が0になって
ました
解決とのことですが
タイムアウトしたときの流れはこれでいいの?
64個を超えるスレッドの全終了待ちってことなのか。
大変ですな。俺はそんなことしたことないや。
タイムアウトしたら次の64個にチャレンジするってことですね。
しばらく何で二重ループにしているのか意味がわからんかった。
俺もまずいような気がする。
動作確認してないけど、なんとなくそう感じる。
深く考えたつもりが恥ずかしながら64個を超えた場合でも、ループにバグもありました
実運用ではスレッドが起きる数が多くても10はないので、スレッド数分
WaitForSingleObject()で検知するようにしました
WaitForSingleObject()/WaitForMultipleObjects()で待つ必要はないと思うけど、
フラグ等でスレッドが終了したかどうか駄目押しで調べるのも必要かもしれません。
それでも、終わってないスレッドは。、「TerminateThread」等を使って終わらせなけれ
ばいけないと思います。
スレッド終了待ち処理の前にスレッドへ終了指示
(メッセージやフラグ等で)が必要では?
その終わらせるスレッドは、終了後処理は必要ないのでしょうか?
(例:ファイルに書き込むスレッドなら、
所持データのファイル書込み→ファイルクローズ)
強制終了は、それでもタイムアウトした時では?
1~複数のスレッド終了待ちなら、
WaitForMultipleObjects()の方がスマートですね。
(引数指定だけですから・・・)