Newsgroup: it.comp.lang.delphi
Titolo: Download multipli

[D6 Win2000]
Dopo un po' di inattività, ho provato a cimentarmi in un download multiplo,
ossia più di un file alla volta.
Allora, la mia app dovrebbe aprire (stile getright) più finestre identiche e
scaricare contemporaneamente n file.
Per scaricare i file, non conoscendo gli Indy, mi ero orientato verso un
componente LiteWeightDownloader, ma senza successo, visto che se avevo
attivato una finestrella (non modale ovviamente) di download e ne attivavo
un'altra, la prima interrompeva il download e proseguiva solo quando la
seconda aveva finito.
Allora mi sono detto "proviamo sto cazz di Indy di cui parlano tutti bene,
ci metterò tutto il giorno ma...", ma i miei timori erano infondati, con un
semplice get su un filestream scarica correttamente, però purtroppo mi fa lo
stesso identico scherzo.
*Allora* ho detto "proviamo a creare un thread separato per creare una
finestrella... fatto (incredibile, finalmente riesco a fare le cose in un
tempo decente), ma nisba, stessa cosa.
Quindi sono giunto alla conclusione che sbagli l'approccio a qualcosa io.
Mi rendo conto che senza source è un po' difficle, ma dovrei postare un bel
po' di codice... e magari qualcuno ha già affrontato questo problema.
-- 
Jax
Journeying Artificial Xenomorph

 po' di codice... e magari qualcuno ha già affrontato questo problema.
Posta un bel po' di codice! ;-)
--
- Carlo -

Quindi sono giunto alla conclusione che sbagli l'approccio a qualcosa io.
Parti dal presupposto che la VCL è mono-thread.
Questo significa che non puoi pretendere di piazzare due componenti su
un form e aspettarti che facciano, *contemporaneamente*, lo stesso
lavoro.  O il componente, al suo interno, crea il proprio thread e si
distacca dal thread principale (e quindi se ne crei 10, lavorano tutti
in contemporanea), oppure crei tu 10 thread e in ogni thread crei un
componente.  Se Maometto non va alla montagna, la montagna va da
Maometto.  Se ho un pò di tempo ti scrivo un pò di codice.
-- 
Andrea Laforgia
#exclude <windows.h>

 Posta un bel po' di codice! ;-)
Uhm, visto che non mi rispondeva nessuno, e che non potevo postare giga e
giga (uff!) di codice, ho provato un po' a circoscrivere il problema, e ho
fatto nel caro vecchio modo: una nuova applicazione con lo stretto
necessario, ovvero due buttons, due IdHTTP (proprio loro), due progressbar
(e anche un IdAntiFreeze per l'occasione).
Sotto c'è il codice, lunghetto ma semplicissimo, ma il problema rimane:
scaricando un file si interrompe il download dell'altro.
Domani comunque provo a cercare qualche info + approfonditamente, vista
anche la mia scarsa conoscenza degli Indy.
----------
procedure TForm1.Button1Click(Sender: TObject);
begin
  fsFile1 := TFileStream.Create('c:\pippo.zip', fmCreate);
  IdHTTP1.Get(IdHTTP1.Host, fsFile1);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
  fsFile2 := TFileStream.Create('c:\pippo2.zip', fmCreate);
  IdHTTP2.Get(IdHTTP2.Host, fsFile2);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if IdHTTP1.Connected then IdHTTP1.Disconnect;
  if IdHTTP2.Connected then IdHTTP2.Disconnect;
  fsFile1.Free;
  fsFile2.Free;
end;
procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCountMax: Integer);
begin
  ProgressBar1.Max := AWorkCountMax;
end;
procedure TForm1.IdHTTP2WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCountMax: Integer);
begin
  ProgressBar2.Max := AWorkCountMax;
end;
procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
begin
  ProgressBar1.Position := AWorkCount;
end;
procedure TForm1.IdHTTP2Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
begin
  ProgressBar2.Position := AWorkCount;
end;


 componente.
Dunque, anch'io avevo pensato la stessa cosa, ma tra il dire e il fare c'č
di mezzo "e il".
Se sei sicuro al 100% che creando un thread che si crea la sua form (e il
relativo componente) puoi fare due cose contemporaneamente, allora o ho
sbagliato qualcosa io facendolo oppure non lo so; ti dico cosě perché
anch'io mi sono fatto un thread che, in esecuzione, crea una form di
download che fa tutto lei (fa partire il download con il suo IdHTTP, e si
aggiorna le sue ProgressBar).
Ovviamente ogni volta che voglio far partire un download creo un thread di
questo tipo e finita lě.
Ho perň qualche dubbio sulle sincronizzazioni.
Comunque, giusto per postare un po' di codice:
procedure TForm1.Button1Click(Sender: TObject);
var
    thrDown: TDownload;
    sUrl, sFile: String;
begin
    //........
      thrDown := TDownload.Create(True);
      thrDown.sURL := sUrl;                       // un URL qualsiasi
      thrDown.sFile := sFile + '.unfinished';
      thrDown.Resume;
end;
// nella unit del thread
procedure TDownload.Execute;
begin
 Synchronize(ApriFinestra);
end;
procedure TDownload.ApriFinestra;
var
 frmDownload: TDownloadForm;
begin
 frmDownload := TDownloadForm.Create(Form1);
 frmDownload.sURL := sURL;
 frmDownload.sFile := sFile;
 frmDownload.Show;
end;
E sull'OnShow della form creata parte automaticamente il download.


 Journeying Artificial Xenomorph
Ciao
Andrea

 Metti i TIdHTTP all'interno dei thread e provi questo.
Ti intrometti? Il ng č di tutti :)
Cioč, tu dici di creare la form di download, e dentro questa mi creo un
thread?
In effetti č piů logica, č vero.
Ci proverň, grazie.


E sull'OnShow della form creata parte automaticamente il download.
Appunto, č sbagliato.
Tu esegui un Synchronize su tutta l'operazione di Show e di gestione
del form.  In questo modo, praticamente, trasformi lo Show in una
sorta di ShowModal (bloccando tutti gli altri).  Il Synchronize deve
servire _solo_ per le operazioni di _aggiornamento_ del form.  Il
componente di download non deve essere nel _form_, deve essere creato
nel _thread_, usato dal thread e il thread deve aggiornare il form
periodicamente.


 sorta di ShowModal (bloccando tutti gli altri).
Adesso che me lo fai notare è effettivamente logico.
Purtroppo la mia scarsissima esperienza con i thread mi ha punito :)
Grazie, spero che non mi farò più sentire su questo argomento ;)


anni... :)
Lavorare in ambienti multi-thread č sempre rognoso.
Se ti puň essere d'aiuto, il capitolo 5 di "Delphi Developer's Guide"
di Teixeira-Pacheco č tutto incentrato sulle "Multithreaded
techniques".


 techniques".
Purtroppo le mie finanze non mi permettono l'acquisto... quello che so sui
thread l'ho letto in un pomeriggio di (gasp) 4 anni fa spulciando un libro
di un mio compagno di banco all'uni...
E poi ci siete voi, chi ha bisogno dei libri :*


 E poi ci siete voi, chi ha bisogno dei libri :*
Se mi dai un indirizzo email valido ti invio il pdf del quinto capitolo di 
Delphi 6 Developer's Guide.
-- 
Ciao,
   Stefano
Una volta che avete conosciuto il volo, camminerete sulla Terra guardando 
il cielo, perché là siete stati e là desiderate tornare (Leonardo da Vinci)
PS: già che usi il delimitatore per la firma, potresti metterlo standard? 
Con lo spazio o senza dopo i due trattini, come vuoi ma senza il 
quadratino.
Grazie.


 techniques".
Una domandina forse stupida: ma il TIdHTTP è un oggetto della VCL?
Questa domanda perché nel thread viene detto esplicitamente
Important: Methods and properties of objects in VCL or CLX can only be used
 in a method called using Synchronize, for example,
Mi verrebbe da pensare di no, visto che non è un componente "Visual",
però... TIdHTTP è un discendente di TComponent, che secondo la guida fa
parte della VCL.


 capitolo di Delphi 6 Developer's Guide.
Azz! :)
garetjax<AT>
libero.it
Che posso dire...... grazie!!


parte della VCL.
La VCL č una libreria che viene "estesa" con la scrittura di nuovi
componenti.  I componenti di terze parti estendono la VCL e sono
soggetti alle stesse regole.


 "Far parte" della VCL è un concetto complesso ;-)
FUNZIONA!!!!!!!!!!
Ehm, scusate l'urlo liberatorio ma non credevo di riuscirci ^____^!!
E' stato un po' complicatuccio anche per il fatto delle form di download
create a runtime, per cui ho dovuto passare al thread come variabile la form
stessa; forse non è il metodo migliore ma è l'unico che sono riuscito a
partorire...
in sostanza la form di download quando viene creata, crea il thread in
questo modo:
  thrDown := TDownload.Create(True);
  thrDown.sURL := sUrl;
  thrDown.sFile := sFile;
  thrDown.frmDownload := Self;
  thrDown.Resume;
e poi è il thread che aggiorna la form che l'ha creato, per esempio:
  frmDownload.ProgressBar1.Max := thrAWorkCountMax;
C'è una pecca stilistica nella unit del thread ma ve la risparmio :)
Sono già contentissimo così!!!


 end;
Cio' che e' in synchronize viene eseguito nel contesto del thread della
VCL; considerato poi che al termine della show finisce anche Execute, il
thread non fa praticamente nulla.
Saluti
Paolo Arosio

 Execute, il thread non fa praticamente nulla.
Rileggendo ho notato l'idiozia del mio codice :)
