Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    [delphi] : thread - non muore

    Salve a tutti
    ho realizzato un'applicazione multi-Thread con Delphi 7 ed un grosso problema... un thread non ne vuole sapere di terminarsi e quindi nonostante l'applicativo si chiuda (o meglio l'interfaccia grafica si chiude) se vado sul taskManager vedo ancora attivo l'eseguibile del programma... cosa devo fare per ucciderlo?
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  2. #2

  3. #3
    Costruttore:
    codice:
    constructor TAggiornaStato.create(q,q1,q2:TADOQuery;priorita:TThreadPriority;vedi_storico:boolean);
    begin
      FreeOnTerminate:=false;
      qry:=q;
      qry2:=q1;
      qry3:=q2;
      esegui:=true;
      inherited Create(False);
    end;
    Procedura che dovrebbe fermare l'elaborazione:
    codice:
    procedure TAggiornaStato.fermaElaborazione;
    begin
      esegui:=false;
    end;
    Procedure dell'execute :
    codice:
    procedure TAggiornaStato.Execute;
    begin
      updateState;
      while (esegui) do
      begin
        try
          if (Terminated) then
            updateState;
        except
          on e:exception do
          messageDlg('Errore Thread: '+trim(e.message),mtwarning,[mbOk],0);
        end;
        Sleep(4000);
      end;
    end;
    quando lo termino faccio :

    codice:
    var
      //dichiarato allinizio ovviamente
      AGGST:TaggiornaStato;
    ...
    
    
    begin
      ....
      AGGST.fermaElaborazione
      //attendo il terminate
      repeat
      until AGGST.terminate;
      AGGST.free;
      AGGST:=nil;
    end;
    Il problema è che ora alle volte rimane incatrato in quel ciclo...
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  4. #4
    Allora, la soluzione così al volo non ce l'ho, però posso darti qualche suggerimento:

    codice:
      esegui:=true;
    Questa variabile "esegui" non ti serve. La usi esattamente per fare quello per cui la proprietà Terminated è preposta.

    codice:
    procedure TAggiornaStato.Execute;
    begin
      updateState;
      while (esegui) do
      begin
        try
          if (Terminated) then
            updateState;
        except
          on e:exception do
          messageDlg('Errore Thread: '+trim(e.message),mtwarning,[mbOk],0);
        end;
        Sleep(4000);
      end;
    end;
    Il controllo del while fallo sulla proprietà Terminated. Poi non capisco una cosa: pare che questo thread richiami "updateState" all'inizio e quando termina, ma durante l'esecuzione non fa nulla, forse hai solo omesso delle parti non significative. Ovviamente la "updateState" finale la puoi mettere fuori dal ciclo while. Inoltre 4000ms di Sleep mi pare decisamente troppo. A proposito, la updateState è thread-safe vero? O aggiorna l'interfaccia grafica?

    codice:
      AGGST.fermaElaborazione
      //attendo il terminate
      repeat
      until AGGST.terminate;
    Meglio fare:

    AGGST.Terminate();
    AGGST.WaitFor();

    (e comunque doveva essere AGGST.terminated).

  5. #5
    Il terminate lo fa ogni qual volta finisce updateState (All'interno della funzione stessa).
    Esegui mi serve per controllare meglio l'uscita dal thread, infatti la uso anche all'interno dell'updateState per fermare i cicli qualora fosse false (faccio delle interrogazioni al database e ciclicamente aggiorno una listView dell'interfaccia grafica richiamando un'altra funzione che sincronizzo).

    Cmq credo di aver risolto il problema: io creavo il Thread durante l'esecuzione dell'evento OnShow della form principale. Ora l'ho spostato, per una necessità diversa, dentro ad un timer che richiamo dall'OnShow e il problema è svanito! Direi quindi che ho avuto un cosidetto colpo di cul...

    Comunque la scelta dei 4 secondi è dettata dal fatto che questo thread serve a dare informazioni tramite l'interfaccia e deve coesistere con altri 4 che rappresentano invece il cuore del programma e non volevo appesantire troppo l'applicativo.

    si è vero sarebbe meglio il AGGST.WaitFor() al posto del ciclo ma con il repeat io posso dare delle istruzioni all suo interno tipo application.processMessage tanto per non lasciare l'applicativo in stato di momentaneo blocco.

    Cmq grazie per l'aiuto.
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  6. #6
    Il terminate lo fa ogni qual volta finisce updateState (All'interno della funzione stessa).
    Questo non mi sembra il massimo, però dipende un po' dalla tua applicazione.

    Esegui mi serve per controllare meglio l'uscita dal thread, infatti la uso anche all'interno dell'updateState per fermare i cicli qualora fosse false
    Che significa "meglio"? Non ho ancora capito perchè non usi Terminated...

    (faccio delle interrogazioni al database e ciclicamente aggiorno una listView dell'interfaccia grafica richiamando un'altra funzione che sincronizzo).
    Se all'interno della updateState accedi ad una TListView, devi richiamarla con Synchronize. Non so se è questo che intendi con "funzione che sincronizzo", comunque è opportuno precisarlo.

    Cmq credo di aver risolto il problema: io creavo il Thread durante l'esecuzione dell'evento OnShow della form principale. Ora l'ho spostato, per una necessità diversa, dentro ad un timer che richiamo dall'OnShow e il problema è svanito! Direi quindi che ho avuto un cosidetto colpo di cul...
    Perchè dal thread accedi a componenti del form principale. Se lo fai senza Synchronize qualche problema ci sarà ancora. Il problema mi pare sia stato spostato, non risolto.

    si è vero sarebbe meglio il AGGST.WaitFor()
    Non è che sarebbe meglio, quello è il sistema corretto.

    tanto per non lasciare l'applicativo in stato di momentaneo blocco.
    L'applicativo non è in blocco, sta chiudendo i thread e questo puoi segnalarlo. Chiaro che se il tuo thread è appena entrato nello Sleep di 4 secondi per quel tempo non può certo chiudersi.

    Cmq grazie per l'aiuto.
    Figurati.

  7. #7
    Originariamente inviato da ESSE-EFFE
    Questo non mi sembra il massimo, però dipende un po' dalla tua applicazione.

    Che significa "meglio"? Non ho ancora capito perchè non usi Terminated...
    Perchè con terminate devo aspettare che finisca i cicli all'interno dell'updatestate che invece interrompo tramite dei controlli con la variabile esegui


    Originariamente inviato da ESSE-EFFE
    Se all'interno della updateState accedi ad una TListView, devi richiamarla con Synchronize. Non so se è questo che intendi con "funzione che sincronizzo", comunque è opportuno precisarlo.

    Perchè dal thread accedi a componenti del form principale. Se lo fai senza Synchronize qualche problema ci sarà ancora. Il problema mi pare sia stato spostato, non risolto.
    Si uso Synchronize ma se faccio partire il Thread nell'onShow poi si bloccava durante il terminate.



    Originariamente inviato da ESSE-EFFE
    L'applicativo non è in blocco, sta chiudendo i thread e questo puoi segnalarlo. Chiaro che se il tuo thread è appena entrato nello Sleep di 4 secondi per quel tempo non può certo chiudersi.
    no lo sleep se esegui e false non lo fa(esempio di una ottimizzazine con la variabile esegui )
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  8. #8
    Perchè con terminate devo aspettare che finisca i cicli all'interno dell'updatestate che invece interrompo tramite dei controlli con la variabile esegui
    Basandomi sul codice da te postato, la variabile esegui la utilizzi anche per terminare il thread. Quindi se anzichè controllare tale variabile all'interno della updateState utilizzi Terminated raggiungi esattamente lo stesso scopo (con la differenza che non aggiungeresti una variabile ridondante e non thread-safe nel programma).

    no lo sleep se esegui e false non lo fa(esempio di una ottimizzazine con la variabile esegui )
    Questo è fuorviante, oltre che sbagliato. Sempre ragionando sul tuo codice, se tu imposti esegui a false (oppure se richiami la Terminate) ed il tuo thread sta già eseguendo la Sleep (o comunque se il thread stesso non sta controllando il valore di esegui o di Terminated) il thread continuerà a fare quello che stava facendo.

  9. #9
    Originariamente inviato da ESSE-EFFE
    Basandomi sul codice da te postato, la variabile esegui la utilizzi anche per terminare il thread. Quindi se anzichè controllare tale variabile all'interno della updateState utilizzi Terminated raggiungi esattamente lo stesso scopo (con la differenza che non aggiungeresti una variabile ridondante e non thread-safe nel programma).

    Questo è fuorviante, oltre che sbagliato. Sempre ragionando sul tuo codice, se tu imposti esegui a false (oppure se richiami la Terminate) ed il tuo thread sta già eseguendo la Sleep (o comunque se il thread stesso non sta controllando il valore di esegui o di Terminated) il thread continuerà a fare quello che stava facendo.
    Il terminate non lo chiamo mai direttamente e nel caso che tu hai menzionato si perde solo qualche secondo ma nulla di più.. cmq ho fatto dei test ed ho visto che fin ora questo è risultato il sistema più performante.

    E poi una variabile membro del thread di tipo booleano non è di fatto thread-safe?
    Di certo hai ragione a dire che è ritondante, ma per il momento è una necessità.

    Sicuramente Farò tesoro dei tuoi consigli e vedo se riesco a rendere più corretto il codice dell'applicazione.

    Grazie ancora.
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  10. #10
    nel caso che tu hai menzionato si perde solo qualche secondo ma nulla di più..
    Certo, ma io intendevo dire che quell'aspetto non lo ottimizzi di certo aggiungendo una variabile.

    cmq ho fatto dei test ed ho visto che fin ora questo è risultato il sistema più performante.
    Sono contento che a te vada bene, però consentimi di non essere d'accordo.

    E poi una variabile membro del thread di tipo booleano non è di fatto thread-safe?
    Forse "di fatto" sì e magari non ti darà mai problemi, ma non è una cosa sicura.

    Di certo hai ragione a dire che è ritondante, ma per il momento è una necessità.
    Se è ridondante non è una necessità. E non ho ancora capito il motivo di questa ridondanza.

    Grazie ancora.
    Di nulla.

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 © 2025 vBulletin Solutions, Inc. All rights reserved.