Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it L'avatar di VaLvOnAuTa
    Registrato dal
    Jun 2002
    Messaggi
    2,003

    [delphi] Bloccare thread

    Ho creato un form che funge da "alert popup" (alla google desktop o msn messenger). All'evento OnShow, viene creato un Thread che dopo 10 secondi dovrebbe far chiudere la popup. E funge bene. Ora il problema è che, all'evento OnClose del popup bisognerebbe distruggere il thread. Il fatto è che se non lo distruggo, il thread continua ad eseguirsi (sballandomi i valori al successivo riavvio del popup), mentre se lo distruggo alla chiusura del popup mi si pianta l'applicazione.
    codice:
    procedure TThreadTimer.Dissolve;
    var i : byte;
    begin
     Timer.Terminate;
     for i:=255 downto 0 do
      Popup.AlphaBlendValue := i; // effetto dissolvenza
     Popup.Close;
    end;
    
    
    procedure TThreadTimer.Execute;
    var i: integer;
    begin
     i := 0;
     while true do
      begin
       sleep(1000);
       i := i + 1000;
       Popup.LblInfo.Caption := IntToStr(10-(i div 1000));
       if i = 10000 then
        Synchronize(Dissolve);
      end;
    end;
    
    procedure TPopup.FormShow(Sender: TObject);
    begin
     AlphaBlendValue := 0;
     Timer := TThreadTimer.Create(false);
     Timer.FreeOnTerminate := true;
    end;
    
    procedure TPopup.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
     Timer.Destroy;
    end;
    Cosa c'è che non va in questo codice?

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    Generalmente, il thread termina quando l'esecuzione del metodo Execute si conclude, ma nel tuo caso ciò non avviene mai perché hai inserito in sostanza un ciclo infinito.

    Per consentire al thread di concludersi correttamente, modifica il tuo ciclo in questo modo:

    codice:
    while not Terminated do
    begin
      // istruzioni del thread
    end;
    Per determinare la conclusione dei lavori del thread, è sufficiente impostare la proprietà Terminated al valore True. Prendendo il tuo esempio:

    codice:
    procedure TThreadTimer.Dissolve;
    var i : byte;
    begin
      for i:=255 downto 0 do
        Popup.AlphaBlendValue := i; // effetto dissolvenza
      Popup.Close;
      Self.Terminated := True;
    end;
    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it L'avatar di VaLvOnAuTa
    Registrato dal
    Jun 2002
    Messaggi
    2,003
    Sì in effetti avevo già fatto una modifica in tal senso.
    (Anche se non è possibile impostare un valore alla proprietà Terminated; esiste la funzione apposta "Terminate" )
    Il problema è che se riapro la popup, imponendo nuovamente un Thread.Execute, mi vede il thread sempre come "Terminated" infatti non comincia alcun countdown.
    Avevo modificato così:
    codice:
    procedure TThreadTimer.Execute;
    var i: integer;
    begin
     i := 0;
     Popup.LblInfo.Caption := IntToStr(10-(i div 1000));
     while not(Terminated) do
      begin
       sleep(1000); // un secondo
       i := i + 1000;
       Popup.LblInfo.Caption := IntToStr(10-(i div 1000)); // mostra i secondi che mancano
       if i = 10000 then
        begin
         Timer.Terminate;
         Synchronize(Dissolve);
        end;
      end;
    end;
    
    procedure TPopup.FormShow(Sender: TObject);
    begin
     AlphaBlendValue := 0;
     if Timer.Terminated then
      Timer.Execute;
    end;
    Però in questo modo, quando ricompare la popup, il counter è fermo a 10 e non entra mai nel ciclo while (probabilmente perchè Terminated è true ma non è possibile assegnare valori, dato che Terminated è read-only)

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    Originariamente inviato da VaLvOnAuTa
    Anche se non è possibile impostare un valore alla proprietà Terminated; esiste la funzione apposta "Terminate"
    Sì, un lapsus, mi ricordavo male.

    Originariamente inviato da VaLvOnAuTa
    Il problema è che se riapro la popup, imponendo nuovamente un Thread.Execute, mi vede il thread sempre come "Terminated" infatti non comincia alcun countdown.
    E' ovvio. Quel thread è già esaurito. Non puoi rilanciare lo stesso thread, o meglio puoi lanciarlo se non lo hai terminato, ma in questo caso è così.

    Avendo impostato peraltro FreeOnTerminate a True, l'oggetto legato al thread viene pure distrutto.

    Non ti rimane che creare semplicemente un nuovo thread ogni volta che ne hai bisogno.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Utente di HTML.it L'avatar di VaLvOnAuTa
    Registrato dal
    Jun 2002
    Messaggi
    2,003
    Hai ragione. Grazie.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.