Что может привести к тому, что поток и приложение C ++ Builder / Delphi не будут закрыты? - PullRequest
2 голосов
/ 13 июня 2011

Однажды во время тестирования мое приложение C ++ Builder / Delphi выдало необработанное исключение в фоновом рабочем потоке. EurekaLog поймал исключение и отправил отчет об ошибке, как я и ожидал, и все оказалось в порядке.

Однако, когда я закрыл главное окно приложения, что-то продолжало работать в фоновом режиме, потому что приложение все еще было указано в диспетчере задач (и ресурсы по-прежнему были открыты).

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

Что может привести к тому, что поток и приложение останутся такими же запущенными даже после закрытия главного окна (и, по-видимому, после вызова PostQuitMessage)?

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

Ответы [ 2 ]

7 голосов
/ 13 июня 2011

Первое правило заключается в том, что основные методы исполнителя потоков должны быть написаны так, чтобы их можно было правильно сигнализировать и завершать работу, а второе правило заключается в том, что вам не следует сначала просто отключить основной поток приложения, а затем надеяться, чтодругие потоки закрываются в свое время, чтобы быть в безопасности, вы должны дать сигнал всем фоновым потокам прекратить работу, дождаться завершения этого завершения и ТОГДА завершить работу основного потока.Пример минимальной THREAD:

procedure TMyThread.Execute;
begin
   Init;
   while not Terminated do
      OneWorkItem; // inside OneWorkItem, you  ALSO need to check for Terminated
end;

Пример минимальной основной формы / основного потока:

   procedure TMyMainForm.CheckAndShutdown;
   begin
     if FPendingShutdownFlag then 
       if AllBackgroundThreadsTerminated then 
             Self.Close;
   end;

Вы можете установить FPendingShutdownFlag и вызвать указанную выше функцию из цикла обработки в режиме ожидания приложения.Когда пользователь нажимает на основную форму FormClose, если AllBackgroundThreadsTeridity возвращает значение false, установите для CanClose значение false и установите вместо него FPendingShutdownFlag := true.

Если вы выполняете бесконечный цикл (при значении true), приложение не выполняетОтключи чисто, даже если тебе так кажется.Каким-то образом приложение завершается, и запущенные потоки могут просто внезапно тихо уходить, или они могут блокировать вас или иным образом вызывать сбой, поскольку они могут использовать ресурсы в потоке 2, которые вы заняты освобождением в потоке 1.

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

1 голос
/ 13 июня 2011

Вы уверены, что рабочий поток завершен, и основной поток не ожидает его завершения?

...