Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : question sur les thread [ Divers / Aide et documentation ] (Sat83)

lundi 21 avril 2008 à 18:06:03 | question sur les thread

Sat83

Bonjour a tous,

J'ai une petite interrogation concernant les threads.

Je souhaite arreter mon application a une heure précise. Mon programme fonctionne parfaitement, et actuellement j'utilise un TTimer avec un Interval de 10 secondes qui regarde que l'heure fixée n'est pas arrivée. Si elle est arrivée, l'application se ferme.

Jusqu'ici tous va bien. Le problème c'est que si mon application plante ou reste bloqué dans un traitement (ca ne devrait pas arrivé, mais on ne sais jamais), elle restera bloqué et elle ne se fermera pas a l'heure (puisque l'application etant planté, elle n'ira pas dans la procédure du Timer).

En gros je voudrais que le thread tourne en boucle en attendant la bonne heure, et que lorsque celle ci arrive, elle ferme l'application ou force la fermeture si l'appli est plantée.

Je me demande donc si je remplace la fonction du Timer par un thread parallèle, est ce que cela marchera même si le thread principale est planté? Ou est ce que cette solution ne vous semble pas correcte (je connais pas encore bien les threads et leurs comportements)?

Merci d'avance

lundi 21 avril 2008 à 18:38:13 | Re : question sur les thread

florenth

Membre Club
Salut !

Si ton thread principal est planté (genre boucle infinie) ou ne vérifie pas périodiquement l'existence de signaux provenant de l'autre thread, ta solution  ne fonctionnera pas.

Cette solution que tu proposes est donc strictement identique à l'autre.
Si ton application est déjà multi-threadée, c'est la solution que je te conseille, sinon tu peux largement garder la version "timer" qui est tout à fait acceptable.

Ce que tu peux faire, par contre, c'est changer la propriété Interval du timer en fonction du temps restant avant la fermeture, pour moins consommer en ressources processeur (même si c'est pas énorme une fois toutes les 10 secondes)

Un truc du genre en gros :

var
  TempsRestant: Double;
begin
  TempsRestant := DateTimeDeFin - Now;
  if TempsRestant <= 0 then
    Close
  else if TempsRestant <= 60 then
    Timer.Interval := 5000
  else if TempsRestant <= 120 then
    Timer.Interval := 40000
  else
    Timer.Interval := 120*60;
end;

A+
Flo

lundi 21 avril 2008 à 18:39:57 | Re : question sur les thread

florenth

Membre Club
J'avais pas vu un détail: "forcer la fermeture"

Dans ce cas, alors tu peux utiliser un thread qui appelle la fonction système qui "tue" les processus. Mais je ne sais pas si un processus peut s'auto-tuer, à essayer...

lundi 21 avril 2008 à 19:23:39 | Re : question sur les thread

Sat83

Pour l'instant j'en suis a la solution avec le Timer.

J'envisage de passer a la solution avec un second thread, mais seulement si c'est utile. C'est pour cette raison que j'ai preféré poser la question avant de me lancer dans un developpement inutile qui m'aurait amené au même resultat.

Dans ce que j'imaginais comme solution,  dans mon second thread je voulais soit fermer le programme normalement si c'est possible, soit killer le processus (en passant par un .bat intermediaire).

lundi 21 avril 2008 à 21:20:53 | Re : question sur les thread

Caribensila

Membre Club

Bonsoir,

« Mais je ne sais pas si un processus peut s'auto-tuer »
 
C'est possible.
Dans ce test, le process s'auto-tue au bout de 4 secondes :

type
  TWaitThread = class(TTHread)
  private
    fProcessHndl : Thandle;
// Handle du process.
  protected
    Constructor Create(Hndl : Thandle);
    procedure Execute; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

var  Wait : TWaitThread;

Constructor TWaitThread.Create(Hndl : Thandle);
  begin
  fProcessHndl := Hndl;
  inherited Create(false);
end;

procedure TWaitThread.Execute;
begin
  while not terminated do begin
    sleep(4000); 
//Le process se suicidera au bout de 4s.
    beep; // Dernier soupir.
    TerminateProcess(fProcessHndl, 0);  
//là, le process est décédé à 100%.
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
  var i : integer;
begin
  Wait := TWaitThread.Create(GetCurrentProcess);
// On lance le Thread.
  i := 1;
  repeat 
//Boucle à la con, mais infinie.
    Edit1.text := inttostr(i);
    Edit1.Refresh;
    inc(i);
  until i = -1;
end;


lundi 21 avril 2008 à 21:31:49 | Re : question sur les thread

Caribensila

Membre Club
... Mais le big problème dans tout ça, c'est que TerminateProcess ne libère aucune ressource...

mardi 22 avril 2008 à 08:46:07 | Re : question sur les thread

Sat83

Merci pour ta solution!

Y'aurait-il un moyen de tenter de fermer le programme "normalement" dans le thread, de detecter si c'est pas possible, et dans ce cas là seulement  forcer la fermeture avec TerminateProcess ?

mardi 22 avril 2008 à 12:29:35 | Re : question sur les thread

Rematrix

Si j'été vous j'ivetrais de faire un terminateprocess, fermer comme ça brutement c pas trés propre éssez plus tôt d'envoyé un sms de type WM_CLOSE  ça feras la faire genre SendMessage(fProcessHndl , WM_CLOSE, 0, 0);.

Matrix

mardi 22 avril 2008 à 12:54:50 | Re : question sur les thread

florenth

Membre Club
Bon alors d'après Cari, le processus peut d'auto tuer
Mais TerminateProcess() libère quand même toutes les ressources (et oui !) ***
Ce qu'il ne fait pas, c'est exécuter les procédures de "finalization", les OnDestroy(), etc...

Donc c'est pas propre si par exemple le programme veut pouvoir sauvegarder son fichier de configuration.

Donc, comme le demande Sat83, on peut ruser :
- Une première demande de fermeture "propre": le sms WM_CLOSE fonctionne parfaitement sur toutes les applications VCL Delphi (ce n'est pas forcément le cas pour les autres langages)
- Si au bout de... disons 5 secondes, le programme ne s'est toujours pas arrêté, on fait appel à TerminateProcess

*** : Quoi que j'ai tout de même un doute pour les fichiers ouverts.

mardi 22 avril 2008 à 13:19:12 | Re : question sur les thread

florenth

Membre Club
Réponse acceptée !
Voila ce que ça donne (testé et approuvé par un échantillon de une personne) :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TAutoTerminateThread = class(TThread)
  private
    FMainWndHandle: THandle;
    FTerminateTime: TDateTime;
    FWaitEvent: Cardinal;
  protected
    procedure Execute; override;
  public
    constructor Create(MainWindowHandle: THandle; EndTime: TDateTime);
    destructor Destroy; override;
    { Obligé de réintroduire cette méthode car on utilise un TEvent,
    ce qui n'est malheureusement pas géré nativement par Delphi }
    procedure Terminate; reintroduce;
  end;

  TFrmTest = class(TForm)
    BtnQuit: TButton;
    BtnPlante: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BtnQuitClick(Sender: TObject);
    procedure BtnPlanteClick(Sender: TObject);
  private
    FTermThread: TAutoTerminateThread;
  end;

var
  FrmTest: TFrmTest;

implementation

{$R *.dfm}

constructor TAutoTerminateThread.Create(MainWindowHandle: THandle;
  EndTime: TDateTime);
begin
  inherited Create(False);
  FreeOnTerminate := True;
  FMainWndHandle := MainWindowHandle;
  FTerminateTime := EndTime;
  FWaitEvent := CreateEvent(nil, True, False, nil);
  if FWaitEvent = 0 then
    RaiseLastOSError;
end;

destructor TAutoTerminateThread.Destroy;
begin
  CloseHandle(FWaitEvent);
  inherited Destroy;
end;

procedure TAutoTerminateThread.Terminate;
begin
  SetEvent(FWaitEvent);
  inherited Terminate;
end;

procedure TAutoTerminateThread.Execute;
var
  WaitTime: Cardinal;
begin
  WaitTime := Trunc(FTerminateTime - Now) * 1000;
  if WaitForSingleObject(FWaitEvent, WaitTime) = WAIT_TIMEOUT then
  begin
    {>> On n'a fait pas appel à Terminate et le temps s'est écoulé: on quitte }

    { D'abord, la méthode "douce" (pas SendMessage car si l'autre thread
    est bloqué, celui-ci aussi va se bloquer) }
    PostMessage(FMainWndHandle, WM_CLOSE, 0, 0);

    { On attend encore un peu pour voir si l'autre thread fait
    appel à Terminate ou s'il est vraiment coincé (5 secondes maxi) }
    if WaitForSingleObject(FWaitEvent, 5000) = WAIT_TIMEOUT then
    begin
      { Coinçage total: suicide obligé ! }
      Beep;
      TerminateProcess(GetCurrentProcess, 1);
    end;
  end;
end;

procedure TFrmTest.FormCreate(Sender: TObject);
begin
  {>> Le programme va se fermer 5 secondes après son ouverture }
  FTermThread := TAutoTerminateThread.Create(Handle, Now + 5.0);
end;

procedure TFrmTest.FormDestroy(Sender: TObject);
begin
  {>> On signale au thread de se terminer: la procédure WaitForSingleObject
  renvoit immédiatement WAIT_OBJECT_0 et le thread se détruit normelement }
  FTermThread.Terminate;
end;

procedure TFrmTest.BtnQuitClick(Sender: TObject);
begin
  Close;
end;

procedure TFrmTest.BtnPlanteClick(Sender: TObject);
begin
  while True do
    Sleep(10);
end;

end.

Alors, qu'en pensez-vous ?


1 2

Cette discussion est classé dans : application, question, heure, thread, threads


Répondre à ce message

Sujets en rapport avec ce message

Question bête sur les threads ! [ par BKnet ] Bonjour tout le monde, J'aimerai savoir si on peut associer un évènement sur un thread ? Si oui comment ? Si non y a t'il une autre solution ? Dans Threads et events [ par Danonne ] Salut a tous.Après de nombreuses recherches sur divers sites et forums, je n'ai pas réussi à trouver une réponse (claire et précise) à ma question exi Utilisation de Threads : Bien ou pas bien ? [ par Francky23012301 ] Salut à tous,Une petite question (Oui encore ) : Je suis entrain de faire un ptit truc . Je met un screenshot ca sera plus rapide que d'expliquer la threads [ par sisi231 ] SISI231Je me suis mis aux threads y'a 2 jours : j'ai un peu compris , j'ai corrigé une erreur grace à synchronize mais il en reste une : (petite expli Mise à jour de la l'heure [ par josserand ] Bonjour !Je souhaite affiché la date et l'heure sur l'interface de mon application.Problème, elle ne s'initialise qu'au démarrage de l'application.J'a simple question [ par jeckman ] je cherche a faire a faire un logiciel en DELPHI ! Mais je ne voit pas comment m'y prendre pour faire ça ! Je vais vous expliquer ! Je travaille a OpenGL et Threads [ par FleX2009 ] Bonjour à tous, voilà j'ai un petit problème : je veux dessiner en OpenGL dans un thread, mon algo est du type : Boucle Dessin Fin boucle // jusque i Un ptite question ;-). [ par Becracker ] Salut les gars, Je voudrais savoir que veux dire le message suivant : [Avertissement] Main.pas(119): Le symbole 'FindData' est propre à une platefor Une question pour les pros de delphi ? [ par Fredelphi ] Bonjour,Est-il possible d'influencer une variable ou un controle d'une application à partir d'une autre application ??Je m'explique : Je lance le prog Comment dialoguer entre deux threads [ par nicolaspennaneach ] Voilà, j'ai deux threads. Un gère les entrées claviers et l'autre gère la connection à une machine distante en telnet.Ce que je souhaiterai savoir c'e


Nos sponsors

Sondage...

CalendriCode

Octobre 2008
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,359 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.