Come liberare un thread in delphi

Ho applicazione con multithreading come chiedere qui.
Voglio terminare il thread, e di iniziare una nuova, quando, in seguito viene chiamato il metodo.

procedure TFRABData.RefreshDataset;
var
  GridUpdater: TGridUpdater;
begin
  if Assigned(updaterThread) and (updaterThread <> nil) then
  begin
    updaterThread.Terminate;
  end;
  GridUpdater := TGridUpdater.Create(True);
  GridUpdater.OwnerForm := Self;
  updaterThread := GridUpdater;
  GridUpdater.FreeOnTerminate := False;
  GridUpdater.Start;
  CodeSite.Send('RefreshDataset executed');
end

ma, quando FreeOnTerminate set di True, ho Violazione di Accesso, ma quando FreeOnTerminate set di False, ho perdita di memoria. Come liberare il thread?

Così si vuole avere uno e solo uno di questo tipo di thread in esecuzione in una sola volta ? In altre parole, quando il RefreshDataset viene chiamato il metodo che si desidera terminare il thread attualmente in esecuzione – interrompere il suo momento l’operazione e diciamo che (ri)avviare ? Se è così, allora la tengo ancora in esecuzione (solo pendente) thread.
Ma, quando RefreshDataset è chiamato, significa che qualcosa è cambiato, ed è necessario eseguire nuovamente il thread dall’inizio, anche quando thread di lavoro corrente non è ancora finite.
Guardando cosa c’è dentro (dalla tua precedente domanda), è meglio creare più di un thread. Si hanno alcune stored procedure di carico e che, probabilmente, è che richiede tempo e potrebbe volerci del tempo prima che si sarebbe in grado di restart il thread, è necessario attendere fino a quando la corrente di funzionamento). No, non è una buona idea, prendendo di nuovo…
Non si deve mai tenere un riferimento a un thread in esecuzione per cui è stata impostata FreeOnTerminate

OriginaleL’autore Niyoko Yuliawan | 2012-09-25

3 Replies
  1. 7

    E in aggiunta a RRUZ risposta, per farlo lavorare con FreeOnTerminate = False:

    Terminate imposta solo la bandiera, non fa nulla di più.

    Cambiare

      if Assigned(updaterThread) and (updaterThread <> nil) then 
      begin 
        updaterThread.Terminate; 
      end; 

    per

      if Assigned(updaterThread) then 
      begin 
        updaterThread.Free; 
      end; 

    Free chiamerà Terminate e WaitFor successivamente per eliminare la vostra perdita di memoria.

    Funziona da combinare @RRuz e @ngln risposta. Evitare di creare thread sospeso e chiamando free, non terminate
    Ho semplicemente realizzare, per terminare il thread corrente, è necessario attendere che la stored proc terminare l’esecuzione, ed è ancora un po ‘ di tempo e rendere la UI di congelamento.
    Sì, è vero. Si potrebbe fare una nuova domanda su come prevenire thát.
    -1 non chiamare MAI Free() su un thread che non è stato segnalato per terminare di sicurezza. NON FARE affidamento sul thread distruttore di chiamare Terminate() e WaitFor() per voi. SEMPRE li chiamano esplicitamente nel proprio codice, invece. Un sacco di persone hanno problemi nel corso degli anni da liberare un thread in esecuzione e lasciando il distruttore di fare la disdetta. Semplicemente non funziona correttamente, e non è il posto giusto per gestire questo comunque.
    È stato dimostrato più e più e più volte che il TThread distruttore NON essere invocata per terminare correttamente il filo se è ancora in esecuzione. Quello che David e stai suggerendo di dangerous. NON FARE affidamento su di esso. Esplicitamente terminare un thread di te, DI gratis.

    OriginaleL’autore NGLN

  2. 10

    È necessario chiamare Terminate(), WaitFor() e Free() tutti insieme, ad esempio:

    procedure TFRABData.RefreshDataset; 
    var 
      GridUpdater: TGridUpdater; 
    begin 
      if Assigned(updaterThread) then 
      begin 
        updaterThread.Terminate; 
        updaterThread.WaitFor; 
        FreeAndNil(updaterThread); 
      end; 
      GridUpdater := TGridUpdater.Create(True); 
      GridUpdater.OwnerForm := Self; 
      GridUpdater.Start; 
      updaterThread := GridUpdater; 
      CodeSite.Send('RefreshDataset executed'); 
    end;
    In questo caso, quando l’OP vuole avere una griglia di aggiornamento il più presto possibile, non vorrei aspettare il filo per terminare. Preferirei usare FreeOnTerminate e solo terminare il thread e crearne un altro. Sicuramente, è necessario essere molto attenti, quando la sincronizzazione di thread dell’interfaccia utente, in quanto c’è una grande gara condizione di rischio dal fantasma thread e gli aggiornamenti non possono essere frequenti a causa del fantasma del numero di thread. Entrambi potrebbe essere risolto attraverso l’organizzazione di tutti i thread di una collezione di un certo limite di fantasmi conte. Con il modello, che OP ha attualmente potrebbe essere probabilmente più semplice di (ri)utilizzare un solo thread.
    Il thread sta utilizzando una connessione al database e la pubblicazione di aggiornamenti dell’interfaccia utente. Se è solo il segnale di filetto esistente per risolvere senza in realtà in attesa per il nuovo thread potrebbe calpestare.

    OriginaleL’autore Remy Lebeau

  3. 5
    1. evitare la necessità di avviare un filo sospeso
    2. modificare il tuo TThread costruttore per ricevere il OwnerForm parametro
    3. impostare il FreeOnTerminate valore nel costruttore del thread.
    4. Avviare il TThread in stato di sospensione.

    qualcosa di simile.

      TGridUpdater = class(TThread)
      private
        FOwnerForm: TForm;
      public
        constructor Create(OwnerForm : TForm); overload;
        destructor Destroy; override;
        procedure Execute; override;
      end;
    
    constructor TGridUpdater.Create(OwnerForm: TForm);
    begin
      inherited Create(False);
      FreeOnTerminate := True;
      FOwnerForm:=OwnerForm;
    end;
    
    destructor TGridUpdater.Destroy;
    begin
    
      inherited;
    end;
    
    procedure TGridUpdater.Execute;
    begin
      //your code goes here
    
    end;

    Ora potete creare il vostro Tthread in questo modo

    GridUpdater:=TGridUpdater.Create(Self); //Just set it and forget it
    Funziona, ma, quando RefreshDataset è chiamato di nuovo quando il thread non è terminata l’esecuzione di sicurezza, è ancora buttare violazione di Accesso
    Provare l’ @NGLN raccomandazioni.
    grazie salvato la mia giornata

    OriginaleL’autore RRUZ

Lascia un commento