Newsgroup: it.comp.lang.delphi
Titolo: Thread

Salve a tutti ..ho bisogno di un aiuto...
quando apro un query che deve recuperare diverse migliaia di records devo
attendere un decina di minuti prima che tale istruzione sia eseguita e in
quel tempo la mia applicazione č bloccata!!
Vorrei aprire il query in un thread cosě ho l'applicazione libera....ma non
mi riesce..non capisco bene il meccanismo...chi mi puň aiutare con un
semplice esempio?
ciao grazie...Raf


Usare i thread non e' molto complicato.. praticamente un thread e' una
porzione di codice che viene eseguita in contemporanea al corpo principale
del programma (che e' un thread pure lui).
Per utilizzare un thread devi derivarti una classe dalla classe astratta
TThread:
type TMioThread=Class(TThread)
 public
  procedure Execute;override;
end;
come vedi devi sempre fare l'override del metodo Execute, che sara' quello
che contiene il codice da eseguire in contemporanea, ma oltre a quello puoi
mettere anche altri membri e metodi a piacere, come in una normale classe.
procedure TMioThread.Execute;
begin
 metti qui il tuo codice per la query.
end;
Una volta dichiarato tutto cio', crei un'istanza del thread:
  MioThread:=TMioThread.Create(true);
Se come parametro metti False, il thread parte subito appena creato, Io
consiglio di mettere true, cosi' il thread viene inizializzato ma non
eseguito. In questo modo puoi riempire e settare eventuali campi del
TMioThread. Poi per eseguirlo si usa:
  MioThread.Resume;
Fin qui e' facilissimo, il problema viene piuttosto quando devi
sincronizzare due thread, (tipo uno deve aspettare la fine dell'altro), in
questi casi devi usare gli oggetti di sincronizzazione di Windows (semafori,
eventi ecc ecc).
Casomai se ti serve aiuto in questo chiedi :-)
Ciao !

 > mi riesce..non capisco bene il meccanismo...chi mi può aiutare con un


 liberare la memoria o terminare l'esecuzione? o non è necessario?
Quando la procedura Execute termina, se il campo FreeOnTerminate e' true,
allora l'oggetto si autodistrugge, liberando la memoria, altrimenti resta li
finche' non chiami tu MioThread.Free. Se il Thread produce qualche output
che devi leggere, magari puoi usare il Free manuale, altrimenti e' molto
comodo il FreeOnTerminate..
ciao !                {MSX}

funzionava ma l' applicazione si bloccava ugualmente.
ovvio :) perchè in quel caso il codice del metodo Execute veniva
comunque eseguito nel contesto del thread principale. Ho dovuto
affrontare un problema simile scrivendomi il mio componente per il
multithreading (quelli della VCL sono troppo pesanti per i miei gusti
- non vedo l'ora di mettere le mie sozze manacce sul sorgente della
CLX), ed ecco, grosso modo, come ho risolto, magari ti sarà d'aiuto
per capire come funziona il TThread (gli omissis sono pezzi di codice
non strettamente relativi al nostro caso):
unit nshCommands;
interface
  uses
    Windows;
  type
    TCommand = class
      private
        myPid: Cardinal;
      (* omissis *)
        myMutexHandle, myThreadHandle: Cardinal;
      (* omissis *)
      public
        constructor Create(Parent: TCommand; CommandLine: String); virtual; 
      (* omissis *)
        // the main body
        procedure CommandMain; virtual; abstract;
      (* omissis *)
    end;
    TCommandClass = class of TCommand;
implementation
  function GlobalCommandMain(Instance: TCommand): Cardinal; stdcall;
  begin
    Instance.CommandMain;
    Result:= ERROR_SUCCESS;
  end;
  constructor TCommand.Create;
  begin
    inherited Create;
    myThreadHandle:=
      CreateThread(nil, 0, @GlobalCommandMain, Self, CREATE_SUSPENDED, myPid); 
    if myThreadHandle = 0 then
      Exit // FIXME: raise nasty exception
    else begin
      myMutexHandle:= CreateMutex(nil, True, nil);
      if myMutexHandle = 0 then
        Exit; // FIXME: raise nasty exception
    end;
  end;
end.
In questo esempio, tra l'altro, manca il metodo Run, che non fa
altro che chiamare ResumeThread usando l'handle del thread contenuto
nell'oggetto, salvato nella variabile myThreadHandle