Какой правильный способ ждать Thread.finalization и поддерживать отзывчивость моего приложения
На самом деле я использую этот код и работает нормально, но мне интересно, если это правильный путь.
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
5 ответов
Призвание Application.ProcessMessages
обычно считается запахом кода. Пусть ваш главный поток простаивает, если ему нечего делать.
Если вы управляете компанией и нуждаетесь в том, чтобы кто-то из ваших работников побежал в магазин и забрал некоторые столь необходимые материалы, вы бы шагали к двери, пока он не вернулся, или вы предпочли бы сидеть в своем офисе, отдыхать и ждать его, и узнаете, что припасы здесь, потому что вы слышите, как он входит в дверь? В любом случае, он потратит столько же времени, но первым делом вымотает твои ноги.
Точно так же, вместо того, чтобы ваш пользовательский интерфейс следил за потоком, отправьте отчет о потоке обратно в пользовательский интерфейс. Один из способов сделать это - использовать поток PostMessage
отправить пользовательское сообщение в форму, которая запустила его, как только оно будет завершено, и поместить обработчик сообщения в форму, чтобы ответить на него.
Класс VCL TThread имеет свой собственный WaitFor()
метод, который перекачивает основную очередь сообщений внутренне при вызове в контексте основного потока:
MyThread.WaitFor;
ShowMessage('i am done');
Это выглядит правильно (если правильно означает, что это делает работу). Что бы я изменил, это подождать немного больше времени (50 мс выглядит хорошо, чтобы поддерживать отзывчивость приложения), не загружая процессор.
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
Конечно, есть другие способы сделать это... <шутка>, но я обычно применяю один из основных инженерных принципов:
если это работает, не трогай это! Шутка>
Я согласен с замечанием Мейсона Уилера, что основной поток лучше всего выполнять, но я бы предложил использовать событие OnTerminate в потоке. Это более "естественный Delphi", и внутренняя логика делает бит PostMessage для вас. Поскольку TThread не является компонентом, вы не можете просмотреть его в инспекторе объектов, и вам придется самостоятельно писать и прикреплять обработчик событий. Он вызывается (в главном потоке!) После завершения / завершения потока.
Хотя все выглядит хорошо, как и в jachguate, я бы использовал значение тайм-аута больше, чем 0. Если вы используете WaitForSingleObject(MyThread.Handle, 100)
тогда основной поток будет ждать немного дольше, что потребляет меньше тактов процессора.
Однако лучшим решением было бы использование сообщений. Ваше приложение запускает поток, а затем переводит все элементы управления в отключенный режим. Затем поток выполняется, и когда он закончится, используйте SendMessage или PostMessage в главном окне, чтобы уведомить его о том, что поток завершен снова. Тогда ваше приложение снова включит каждый элемент управления (и все остальное). Преимущество этого заключается в том, что вы поддерживаете "естественную" цепочку сообщений для приложения, а не запускаете собственную цепочку сообщений с этим решением.
К сожалению, метод сообщения имеет один недостаток: если поток завершает работу, то сообщение не будет отправлено обратно, поэтому план резервного копирования будет практичным. Например, добавив элемент управления таймером к вашей основной форме, который каждую секунду проверяет, жив ли поток. Если нет, он также просто активирует форму снова, отключая себя снова.