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