Qu’est-ce qui pourrait empêcher un thread et une application C ++ Builder / Delphi de s’arrêter?

Une fois, pendant le test, mon application C ++ Builder / Delphi a généré une exception non capturée dans un thread de travail en arrière-plan. EurekaLog a attrapé l’exception et envoyé un rapport d’erreur, comme je l’espérais, et tout semblait bien se passer.

Cependant, lorsque j’ai fermé la fenêtre principale de l’application, quelque chose est resté en arrière-plan, car l’application était toujours répertoriée dans le gestionnaire de tâches (et les ressources étaient toujours ouvertes).

J’ai essayé de dupliquer ce problème, en introduisant délibérément divers bogues dans le thread de travail en arrière-plan, mais je ne peux pas.

Qu’est-ce qui pourrait faire en sorte qu’un thread et une application continuent à fonctionner comme ceci, même après la fermeture de la fenêtre principale (et, vraisemblablement, que PostQuitMessage a été appelé)?

Comment puis-je m’assurer que l’application s’arrête toujours proprement?

La première règle est que les principales méthodes d’exécution de threads doivent être écrites pour qu’elles puissent être signalées et arrêtées correctement, et la seconde règle est que vous ne devez pas simplement fermer le thread principal de votre application, puis espérer que les autres threads soient fermés. vers le bas dans leur propre temps, pour être sûr, vous devez signaler à tous les threads d’arrière-plan d’arrêter, attendre la fin de cet arrêt, puis arrêter le thread principal. Un exemple THREAD minimal:

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

Un exemple minimal de formulaire principal / principal:

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

Vous pouvez définir FPendingShutdownFlag et avoir la fonction ci-dessus appelée depuis la boucle de traitement inactive de l’application. Lorsque l’utilisateur clique sur le formulaire principal FormClose, si AllBackgroundThreadsTerminated renvoie false, définissez CanClose sur false et définissez à la place le FPendingShutdownFlag := true .

Si vous faites une boucle sans fin (bien que true), l’application ne s’arrête pas proprement, même si cela vous ressemble. D’une manière ou d’une autre, l’application est terminée et les threads en cours d’exécution peuvent disparaître soudainement, ou ils peuvent vous bloquer ou vous bloquer, car ils peuvent utiliser des ressources du thread 2 que vous êtes en train de libérer dans le thread 1.

Vous pouvez avoir une ou plusieurs conditions de course intentionnelles car vous n’avez peut-être pas écrit votre méthode d’exécution de threads pour pouvoir être interrompue ou vous pouvez commencer la fermeture du thread principal de l’application et de la VCL et de ses objects avant d’être sûr complètement fermé.

Êtes-vous sûr que le thread de travail s’est terminé et que le thread principal n’attend pas qu’il se termine?