Newsgroup: it.comp.lang.delphi
Titolo: Approccio ai thread

Ciao a tutti,
In primis, BUONE FESTE
Posto questo mex per chiedere delucidazioni sull'utilizzo dei thread, in 
quanto sto avendo un problema di difficile soluzione.
In una applicazioncina di collaudo che sto realizzando per una scheda 
elettronica, vorrei utlizzare un form principale contenente 8 frame. 
All'interno degli 8 frame, uguali, è contenuta sia la parte grafica, sia 
la parte di codice necessaria al test di una singola scheda.
Il singolo test, se lanciato direttamente, senza usare thread, funziona 
senza problemi.
Ovviamanete io vorrei poter testare piu di una scheda alla volta, e per 
farlo vorrei lanciare ogni singolo test in un thread separato.
Per fare questo, richiamo una procedura "test" del frame, questa 
procedura esegue i singoli test necessari alla scheda, e segnala 
graficamente nel frame vari messaggi relativi al test (ci sono alcuni 
LED della JVCL, una progess bar sempre della JVCL etc..)
Potrebbe esserci quache problema dato che non ho usato syncronize, ma 
NON ho idea di come usarlo applicato a una situazione come questa.
Purtrooooppo (come diciamo nel bresciano e come zelig ha insegnato a 
tutt' Italia) a volte il tread del collaudo si impappa. Apparentemente 
va in sospensione. Il risultato di questo è un blocco della 
applicazione, che non si riesce piu a chiudere, nemmeno da task manager, 
e che quindi non si riesce nemmeno piu a riavviare.
Ho realizzato un esempio semplificato usando lo stesso aproccio, ma 
questo pare funzionare, senza particolari problemi.
Il codice di esempio che "funziona" è questo:
http:\\
www.snipp.org
\gian\threadtest.zip
Magari potete usarlo come base per tirarmi le orecchie e suggerirmi come 
dare una sistemata.
ZioGian
PS- Allego il codice delle unit per chi non si fida a scaricare i file 
dal SimpsonNuclearItalianPowerPlant ;-)
//codice del form principale, con 4 frame
unit Unit1;
interface
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
Forms,
   Dialogs, StdCtrls, Unit2;
type
   TForm1 = class(TForm)
     F1: TFrame2;
     F2: TFrame2;
     F3: TFrame2;
     F4: TFrame2;
     Button1: TButton;
     Button2: TButton;
     Button3: TButton;
     Button4: TButton;
     procedure StartThread(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end;
   TBackground = class(TThread)
     valore: integer;
     constructor create(StartSuspended: Boolean; Parametro: integer);
     procedure execute; override;
     end;
var
   Form1: TForm1;
   thread1, thread2, thread3, thread4: TBackground;
implementation
{$R *.dfm}
procedure TForm1.StartThread(Sender: TObject);
begin
   if sender = Button1 then begin
     thread1 := TBackground.create(true, 1);
     thread1.Resume;
     end;
   if sender = Button2 then begin
     thread2 := TBackground.create(true, 2);
     thread2.Resume;
     end;
   if sender = Button3 then begin
     thread3 := TBackground.create(true, 3);
     thread3.Resume;
     end;
   if sender = Button4 then begin
     thread4 := TBackground.create(true, 4);
     thread4.Resume;
     end;
end;
{ TBackground }
constructor TBackground.create(StartSuspended: Boolean; Parametro: integer);
begin
   inherited create(StartSuspended);
   StartSuspended := true;
   Priority := tpIdle;
   valore := parametro;
end;
procedure TBackground.execute;
begin
   case valore of           //come si fa a sapere il nome dell'istanza 
della classe ?
     1: form1.F1.test;
     2: form1.F2.test;
     3: form1.F3.test;
     4: form1.F4.test;
     end;
end;
end.
//codice del frame
unit Unit2;
interface
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
Forms,
   Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, 
IdTCPClient,
   IdHTTP;
type
   TFrame2 = class(TFrame)
     CB: TCheckBox;
     Lbl: TLabel;
     HTTP: TIdHTTP;
     LblHTTP: TLabel;
     procedure test;
   private
     { Private declarations }
   public
     { Public declarations }
   end;
implementation
{$R *.dfm}
procedure TFrame2.test;
var
   i, offset: integer;
   ip: string;
begin
   //qi vengono eseguite una serie di operazioni di I/O su una scheda 
dedicata, su bus USB
   for i :=  0 to 10 do begin
     sleep(500);
     application.processmessages;
     cb.Checked := not cb.Checked;
     Lbl.Caption := inttostr(i) + '/10';
     LblHTTP.Caption := '...';
     ip :=  http.Get('http:\\
checkip.dyndns.org
');
     offset := pos('Current IP Address: ', ip) + 20;
     ip := copy(ip, offset, length(ip) - offset);
     offset := pos('</body>', ip) - 1;
     ip := copy(ip, 1, offset);
     LblHTTP.Caption := ip;
   end;
   Lbl.Caption := 'END';
end;
end.

Cosi, per sommi capi, sempre per come la vedo io e tutto rigorosamente IMHO,
afronterei diversamente il problema.
Il codice specifico per il test lo inserirei nel thread e non nel frame.
Anzi, per ogni test farei un thread apposito(ti parlo di definizione
dell'oggetto). Questo thread lo farei creare al frame specifico (il frame1
istanzia il thead1, il frame2 il thread2 etc, considerando che frame1
visualizza i result del test fatto dal thread1, etc)
Poi,
procedue MyThread.ShowREsult;
begin
  qui hai diverse possibilita, o aggiorni direttamente gli oggetti del
frame, o imposti sul frame le variabili che verranno aggiornate, vedi tu.
end;
Quando devi visualizzare i risultati dal thread chiami
 Synchronize(ShowResult);
Spero di essere stato chiaro e non aver dimenticato nulla!
Bye,
Raktzo

 quanto sto avendo un problema di difficile soluzione. [...]
Hai già letto questo tutorial - a mio avviso - molto ben fatto?
http://makeashorterlink.com/?R206130F8
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

 
E' anche quello che volevo fare io. Ma non  sono riuscito a usare i 
thread nel frame. Pensavo di provare beginthread e endthread, ma mi 
sembra "leggermente" compesso come aproccio.
Non è che perderesti 2 minuti a modificare il mio esempio in questo modo ?
ZioGian

 
No, non lo avevo letto. Grazie, ci guardo.
ZioGian

La tua mail?
Bye,
Raktzo

 Raktzo
uff.tecnico_CANCELLAMI_@_ERADICAMI_globaltronic.it
graz

 la parte di codice necessaria al test di una singola scheda.
Non č il frame che deve creare ed avviare il thread, in quanto il frame č
solo delegato a contenere la grafica relativa ad ogni monitoraggio.  Vi
deve essere una classe di monitoring, che fa da thread manager, la quale
si occupa di lanciare un thread per ogni scheda da monitorare, fa sě che
ogni thread comunichi lo stato dell'acquisizione (mediante PostMessage,
NON mediante Synchronize) ed aggiorna, di conseguenza, il frame relativo.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it