Какой правильный способ ждать Thread.finalization и держать мое приложение отзывчивым - PullRequest
13 голосов
/ 16 ноября 2010

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

  while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
    Application.ProcessMessages;

  ShowMessage('i am done');

Ответы [ 5 ]

13 голосов
/ 18 ноября 2010

Класс VCL TThread имеет свой собственный метод WaitFor(), который перекачивает основную очередь сообщений внутри системы при вызове в контексте основного потока:

MyThread.WaitFor; 
ShowMessage('i am done'); 
8 голосов
/ 16 ноября 2010

Вызов Application.ProcessMessages обычно считается запахом кода. Пусть ваш главный поток простаивает, если ему нечего делать.

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

Аналогично, вместо того, чтобы ваш пользовательский интерфейс следил за потоком, отправьте отчет о потоке обратно в пользовательский интерфейс. Один из способов сделать это - заставить поток использовать PostMessage для отправки настраиваемого сообщения в форму, запустившую его после завершения, и поместить обработчик сообщения в форму для ответа на него.

2 голосов
/ 16 ноября 2010

Я согласен с замечанием Мейсона Уилера, что основной поток лучше всего выполнять, но я бы предложил использовать событие OnTerminate в потоке.Это более «естественный Delphi», и внутренняя логика делает бит PostMessage для вас.Поскольку TThread не является компонентом, вы не можете просмотреть его в инспекторе объектов и должны самостоятельно написать и прикрепить обработчик событий.Он вызывается (в основном потоке!) После завершения / завершения потока.

2 голосов
/ 16 ноября 2010

Это выглядит правильно (если правильно означает, что это делает работу).Что бы я изменил, так это подождал немного больше времени (50 мс выглядит хорошо, чтобы поддерживать отзывчивость приложения), не тратя процессор.

while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
  Application.ProcessMessages;
ShowMessage('i am done');

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

, если он работает, не трогай его!

1 голос
/ 16 ноября 2010

Хотя все выглядит хорошо, как jachguate Я бы использовал значение времени ожидания больше, чем 0. Если вы используете WaitForSingleObject(MyThread.Handle, 100), то основной поток будет ждать немного дольше, что потребляет меньше циклов ЦП.
Однако лучшим решением было бы использование сообщений. Ваше приложение запускает поток, а затем переводит все элементы управления в отключенный режим. Затем поток выполняется, и когда он закончится, используйте SendMessage или PostMessage в главном окне, чтобы уведомить его о том, что поток завершен снова. Тогда ваше приложение снова включит каждый элемент управления (и все остальное). Преимущество этого заключается в том, что вы поддерживаете «естественный» цикл сообщений для приложения, а не запускаете собственный цикл сообщений с этим решением.
К сожалению, метод сообщения имеет один недостаток: в случае сбоя потока сообщение не будет отправлен обратно, поэтому план резервного копирования будет практичным. Например, добавив элемент управления таймером к вашей основной форме, который каждую секунду проверяет, жив ли поток. Если нет, он также просто активирует форму снова, снова отключая себя.

...