2012-05-24 2 views
4

Что произойдет, если мы насильно убить запущенную нитьУбить выполняемый поток

У меня есть поток, а именно RecordThread(), который вызывает некоторую сложную и отнимает много времени функции. В этих функциях я использую примерку уловы блоков, выделение и открепление память и использование критических секции переменных и т.д.

как

void RecordThread() 
    { 
    AddRecord(); 
    FindRecord(); 
    DeleteRecord(); 
    // ... 
    ExitThread(0); 
    } 

После создания этой темы, я сразу же убить его до завершения нити его исполнение. В этом случае, что происходит, если поток принудительно убит? Выполняют ли внутренние функции (AddRecord, DeleteRecord) их выполнение после того, как мы убили нить?

ответ

13

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

Я предполагаю, что вы имеете в виду вы используете TerminateThread() следующим образом:

HANDLE thread = CreateThread(...); 

// ... 
// short pause or other action? 
// ... 

TerminateThread(thread, 0); // Dangerous source of errors! 
CloseHandle(thread); 

Если это так, то нет, поток выполнения RecordThread() будет остановлен именно там, где это в то время, другой поток вызывает TerminateThread(). В соответствии с примечаниями в документации TerminateThread() эта точна точка несколько случайна и зависит от сложных проблем времени, которые не поддаются контролю. Это означает, что вы не можете обработать правильную очистку внутри потока и, следовательно, you should rarely, if ever, kill a thread.

Правильный способ запросить нить до конца является использование WaitForSingleObject() следующим образом:

HANDLE thread = CreateThread(...); 

// ... 
// some other action? 
// ... 

// you can pass a short timeout instead and kill the thread if it hasn't 
// completed when the timeout expires. 
WaitForSingleObject(thread, INFINITE); 
CloseHandle(thread); 
+1

Чтобы сделать его более явным: 'TerminateThread' может убить ваш поток в середине инструкции' i ++'. Он не пытается искать «хорошие» точки, такие как вызовы функций. – MSalters

+1

Обратите внимание, что POSIX сильно отличается от API Win32 в этом отношении (по умолчанию, если поток не изменил настройки его отмены), он действительно только убьет ваш поток в точке отмены. Поэтому, не считаясь с опасностью, он не так опасен везде и, следовательно, не «переносится» :-) – Damon

+0

Если это не очевидно из других комментариев, еще несколько причин, почему вы никогда не должны использовать TerminateThread: [Windows начала собирать действительно большие куски мусора TerminateThread на тротуаре, но он все еще мусор на тротуаре] (http://blogs.msdn.com/b/oldnewthing/archive/2015/08/14/10635157.aspx) –

2

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx

ExitThread является предпочтительным способом выхода нити в коде C. Однако в коде C++ поток выходит из перед тем, как можно будет вызвать любые деструкторы или любую другую автоматическую очистку. Поэтому в коде C++ вы должны вернуться из своей функции потока.

Однако вызовы функций, конечно, будут выполнены, потому что они вызываются перед ExitThread().

+0

Что делать, если у них не хватает времени на выполнение? – sharptooth

+0

@sharptooth как в однопоточном коде, последовательная согласованность гарантирует, что все строки перед ExitThread() будут завершены. –

3

убивает нить является последним средством, - как Андре заявил, что оставляет данные в неизвестном состоянии, вы никогда не должны делать, если thread работает с общим объектом. Лучший выбор, чтобы уведомлять нить, чтобы закончить работу по:

-при глобальных летучих (важно) переменному, которая изменяется только основным потоком и протестирована рабочими
-при сигнала объекты синхронизации типа (в основном событие) также устанавливаются основной темой и проверены работниками

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