TerminateThread - плохая идея, особенно если ваш поток использует объекты синхронизации, такие как мьютексы. Это может привести к освобождению памяти и дескрипторов, а также к тупикам, поэтому вы правы, что вам нужно сделать что-то еще.
Как правило, способ завершения потока - это возврат из функции, которая определяет поток. Основной поток сигнализирует рабочему потоку о выходе, используя объект события или даже простое логическое значение, если это проверяется достаточно часто. Если рабочий поток ожидает с WaitForSingleObject
, вам может потребоваться изменить его на WaitForMultipleObjects
, где один из объектов является событием. Основной поток вызовет SetEvent
, а рабочий поток проснется и вернется.
Мы действительно не сможем предоставить какой-либо полезный код, если вы не покажете нам, что делаете. В зависимости от того, что делает рабочий поток и как ваш основной поток передает ему информацию, он может выглядеть очень по-разному.
Кроме того, в [сейчас очень старом] MSVC вам необходимо использовать _beginthreadex
вместо CreateThread
, чтобы избежать утечек памяти в CRT. См. MSKB # 104641 .
Обновление:
Одно из применений рабочего потока - это «таймер», чтобы выполнять некоторые операции через регулярные промежутки времени. Самое простое:
for (;;) {
switch (WaitForSingleObject(kill_event, timeout)) {
case WAIT_TIMEOUT: /*do timer action*/ break;
default: return 0; /* exit the thread */
}
}
Другое использование - делать что-то по требованию. В основном то же самое, но с таймаутом, установленным на INFINITE
и выполняющим некоторые действия на WAIT_OBJECT_0
вместо WAIT_TIMEOUT
. В этом случае вам потребуются два события: одно, чтобы поток проснулся и выполнил какое-то действие, другой - чтобы он проснулся и вышел:
HANDLE handles[2] = { action_handle, quit_handle };
for (;;) {
switch (WaitForMultipleObject(handles, 2, FALSE, INFINITE)) {
case WAIT_OBJECT_0 + 0: /* do action */ break;
default:
case WAIT_OBJECT_0 + 1: /* quit */ break;
}
}
Обратите внимание, что в цикле важно сделать что-то разумное, если WFSO / WFMO вернет ошибку вместо одного из ожидаемых результатов. В обоих приведенных выше примерах мы просто относимся к ошибке, как если бы нам дали сигнал о выходе.
Вы можете достичь того же результата в первом примере, закрыв дескриптор события из основного потока, в результате чего рабочий поток получит ошибку из WaitForSingleObject
и выйдет, но я бы не рекомендовал такой подход.