2010-10-28 3 views
20

В delphi метод в TThread завершается. Кажется, что subthread не может убить другой поток, вызвав завершение или освобождение. Например, A (основная форма), B (единица резьбы), C (другая форма).Как убить нить в delphi?

B отправляет данные в основную форму и C (вызывая syncronize), мы попытались завершить B внутри C, пока B выполняет вызов B.terminate. Но этот метод не работает, и B все еще работает до тех пор, пока он не завершится в методе выполнения.

Пожалуйста, помогите. Заранее спасибо.

ответ

41

Вы должны проверить Завершить в теме, чтобы это работало. Например:

procedure TMyThread.Execute; 
begin 
    while not Terminated do begin 
    //Here you do a chunk of your work. 
    //It's important to have chunks small enough so that "while not Terminated" 
    //gets checked often enough. 
    end; 
    //Here you finalize everything before thread terminates 
end; 

С этим, вы можете позвонить

MyThread.Terminate; 

И это будет прекратить, как только он закончит обработку другой кусок работы. Это называется «изящным завершением потока», потому что сам поток имеет возможность завершить любую работу и подготовиться к завершению.

Существует еще один способ, называемый «принудительное завершение». Вы можете позвонить:

TerminateThread(MyThread.Handle); 

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

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

+1

спасибо Timo. Четкий ответ и примеры. – Dylan

+0

И спасибо вам. очень хороший пример. – Dylan

+3

Это может не только приложение, но и ресурсы, используемые thead, не будут освобождены. TerminateThread() - это вызов «экстремального отношения». – 2010-10-28 18:22:39

12

Terminate не убивает нить; он устанавливает свойство Terminated, чтобы сообщить поток, который он должен завершить. Это обязанность потока следить за Terminated и закрывать себя изящно.

3

Весь метод Terminate делает ли это свойство Terminated равным true. Поэтому вам нужно вручную проверить это свойство и затем выйти из метода потока, если для него установлено значение true.

0

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

14

На самом деле,

В настоящее время наибольшее количество голосов ответ на этот вопрос неправильно (так 34 upvoters ...) в отношении как принудительно убить нить.

Вы неThreadId как параметр TerminateThread процедура. Использование ThreadId вызовет, скорее всего, ошибку «Недопустимый дескриптор» или в худшем случае scenerio - убьет другой поток.

Вы должны пройти thread handle в качестве параметра:

TerminateThread(MyThread.Handle); 

Подробнее о различиях между ручкой потока и ид можно найти here.

Редактировать

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

+0

@kobik да, и я сделал это в прошлом, но посмотрите, как работает это сообщество: многие люди дали +1, не проверяя, правильно ли он ответил. – Wodzu

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