Da gibt es mehrere Möglichkeiten. Die Einfachste wäre, dem Thread eine Property vom Typ TProgressBar zu verpassen. Dann könnte man sich auch das Event sparen, da dann der Thread direkt auf seine Property zurückgreifen und sie synchronisiert aktualisieren könnte. Der Nachteil ist die starke Bindung, denn wenn man später einmal die ProgressBar gegen z.B. eine TGauge austauschen möchte, muss man an mehreren Stellen ändern. Um also flexibel zu bleiben, lassen wir unseren Event so wie er ist. Nun müssen wir noch irgendwie Thread und das zu aktualisierende Control miteinander verknüpfen. Das ginge beispielsweise mit einem Record und einer Liste.
Delphi-Quellcode:
type
PVerknuepfung = ^TVerknuepfung;
TVerknuepfung = record
Thread: TDownloadThread;
ProgressBar: TProgressBar;
end;
Wenn wir nun noch eine TList anlegen, können wir dort Elemente vom Typ PVerknuepfung reinpacken.
Delphi-Quellcode:
var
Verknuepfung: PVerknuepfung;
PB: TProgressBar;
DT: TDownloadThread;
begin
PB := TProgressBar.Create(nil);
PB.Parent := ...
//usw.
DT := TDownloadThread.Create;
//usw.
New(Verknuepfung);
Verknuepfung^.Thread := DT;
Verknuepfung^.ProgressBar := PB;
Liste.Add(Verknuepfung);
end;
Wenn nun einer der Threads das Event feuert, könnte man die Liste durchlaufen und schauen, in welchem Element er drinsteht (er übergibt sich ja selbst im Sender-Parameter).
Delphi-Quellcode:
Index := 0;
PB := nil;
while (Index < Liste.Count) and not Assigned(PB) do
begin
if TVerknuepfung(Liste[Index]^).Thread = Sender then
PB := TVerknuepfung(Liste[Index]^).ProgressBar;
inc(Index);
end;
So, nun haben wir die zugehörige ProgressBar ermittelt (oder auch nicht, dann ist sie nil) und können sie aktualisieren.
Delphi-Quellcode:
if Assigned(PB) then
PB.Position := ErrechneterWert;
Das mag jetzt nicht die allereleganteste Methode sein, sie sollte aber eigentlich funktionieren (ohne Gewähr, da aus dem Kopf getippt) und halbwegs verständlich sein.