2013-08-27 2 views
4

У меня есть основной поток, который принимает действия, требующие определенного времени. Поэтому я создаю поток и делегирую ему задание. Эта функция выполнения вызывается основным потоком при получении заданий. каждая работа реализует это выполнение.Когда звонить CloseHandle?

Return_type execute(Arguments_here) { 

// if a file read case 
DWORD threadId; 
HANDLE hThread = CreateThread( 
     NULL,     // default security attributes 
     0,      // use default stack size 
     MyAsyncFileRead,  // thread function name 
     details,   // argument to thread function 
     0,      // use default creation flags 
     &threadId); // returns the thread identifier 
// else do other work 
} 

Теперь, так как я не хочу ждать в главном потоке, я не называю WaitForSingleObject. [Мои знания о потоках в Windows низки. поэтому, если это не требуется, простите меня]

Если я подожду, когда нить закроется, она будет ждать мой основной поток. Я не хочу этого делать. Итак, когда я называю CloseHandle?

Когда у вас есть 10 заданий в руке и один создает 10 потоков, а затем дождался завершения всех 10 потоков, тогда он выглядит хорошо для wait_for_multiple_objects, а затем вызывает CloseHandle для каждого дескриптора.

Но что я должен делать в этом случае?

[Я полагаю, что этот вопрос был бы уместен для всех ОС, так что их тоже помечали. ]

+0

Не беспокойтесь об этом и используйте '' :) – chris

+0

Очевидно, что вы указали все причины немедленного вызова CloseHandle (hThread). После проверки, что вам действительно удалось запустить его, конечно. –

ответ

5

Если вы действительно не заботитесь о ожидании потока, вы действительно можете закрыть его сразу после создания потока.

Однако я категорически не рекомендую это делать. Вы должны всегда ждать выхода нитей (желательно в чистом, четко определенном виде). Если этого не было сделано раньше, подождите каждый поток, который вы породили, когда программа выйдет. Всегда, никаких исключений.
Не оставляйте main, не зная, продолжают ли выполняться другие потоки. Если нужно, убейте их трудным путем (хотя желательно, пусть они изящно выходят из строя контролируемым образом и ждут его).

Если вы не подождите, пока нитки закончатся, вы можете увидеть странные условия выхода из строя на выходе. Или, что еще хуже, вы можете не видеть их, и только пользователи/клиенты жалуются, что один раз сто раз файл конфигурации поврежден (или, что еще хуже, файл данных) .Теперь представьте, что они могут продемонстрировать шаг за шагом, что они делают, и вы можете сказать, что они все делают правильно, и нет никакого способа, чтобы что-то могло пойти не так.
Удачи, выяснив, что авария связана с тем, что рабочий поток продолжает работать с каким-либо объектом (или глобальным состоянием), который был просто освобожден выходящим основным потоком, явно или неявно с помощью ЭЛТ.

Конечно, ваша позиция может заключаться в том, что рабочий поток выйдет задолго до завершения программы в любом случае, так зачем беспокоиться. Тем не менее, это играет русскую рулетку.


Это не выдумка, но то, что я на самом деле видел произойти раньше.

+0

Спасибо за великолепное понимание. Перемещение в std :: thread решит эту проблему. ? –

+0

Использование std: thread делает ваш код переносимым, но не решает это или любое другое состояние гонки. Вы все равно должны убедиться, что доступны только действительные объекты (или память), в том числе при выходе из программы. Присоединение ко всем потокам гарантирует, что на выходе ничего не получится неожиданно. – Damon

+0

Есть ли что-то вроде threadpool, которые я могу создать глобально, а затем делегировать эту тему. И если моя программа заканчивается, тогда я просто буду делать threadpool.close(), которая будет блокироваться до тех пор, пока все потоки не закончится. ? –

1

Вы можете использовать unique_ptr<HANDLE, CloseHandle> threadHandle - если у вас есть подходящее место для переменной threadHandle, сохраняемых/помещен ..

Или, если вы на самом деле не нужны ручки, просто закройте его сразу после запуска thread, так как дескриптор действительно полезен, если позже вы заботитесь о потоке.

Из MSDN CreateThread документов:

Объекта нити остается в системе, пока поток не имеет прекращается, и все ручки к нему были закрыты с помощью вызова CloseHandle.

Если на каком-то более позднем этапе вам нужна ручка для резьбы, вы можете всегда использовать OpenThread, чтобы получить «новый» ручек. Предполагая, конечно, вы не «проиграли» threadId.

Конечно, правильным решением на C++ является использование std::thread.

+0

Мне не нужна ручка :) –

Смежные вопросы