TerminateThread - плохая идея, особенно если ваш поток использует объекты синхронизации, такие как мьютексы. Это может привести к невыпущенной памяти и ручкам, а также к взаимоблокировкам, поэтому вы правы, что вам нужно сделать что-то еще.
Как правило, путь, которым заканчивается нить, должен возвращаться из функции, определяющей поток. Основной поток сигнализирует, что рабочий поток выйдет с использованием объекта события или даже простого логического, если он проверен достаточно часто. Если рабочий поток ждет WaitForSingleObject
, вам может потребоваться изменить его на WaitForMultipleObjects
, где один из объектов - это событие. Основной поток вызовет SetEvent
, и рабочий поток проснется и вернется.
Мы действительно не можем предоставить какой-либо полезный код, если вы не покажете нам, что делаете. В зависимости от того, что делает рабочий поток, и как ваш основной поток передает ему информацию, он может выглядеть совсем по-другому.
Кроме того, в рамках [сейчас очень старого] MSVC вам необходимо использовать _beginthreadex
вместо CreateThread
во избежание утечек памяти в ЭЛТ. См. MSKB #104641.
Update:
Один использование рабочего потока является как «таймер», чтобы сделать некоторые операции на регулярной основе. В наиболее тривиальной форме:
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
и закроется, но я бы не рекомендовал этот подход.
Функция обратного вызова потока является for (;;), и все. Ничего необычного. поэтому, я повторю вопрос, используя WaitForSingleObject() и SetEvent(), как я могу сигнализировать о моем потоке, который мне нужно закончить? Если я вызову SetEvet (FinishEvent), то WaitForSingleObject() вернет что? 0? 1? -1? – Uri
@Uri Когда вы вызываете 'SetEvent',' WaitForSingleObject' вернет 'WAIT_OBJECT_0' (что равно 0). Когда вы упомянули использование 'WaitForSingleObject', я предположил, что это означало, что вы уже использовали это событие, чтобы сигнализировать рабочему потоку что-то делать (кроме выхода).Также обратите внимание, что в некоторых случаях вам нужно сигнализировать поток wotker для выхода, а затем дождаться, пока он фактически остановится, прежде чем продолжить. (Вы можете использовать 'WaitForSingleObject' для дескриптора потока для этой цели). –
+1 Это ответ, который я бы дал. Делал это так много раз. –