![]() |
Globale Thread function ?
Hi,
ist es möglich eine globale function oder procedure zu setzen, die in allen laufenden Threads aufgerufen wird ? Problem ist folgendes. Idhttp ist in einem Thread. 3 Threads laufen momentan parallel und schreiben ihren Status in eine Listview. Wenn nun ein Thread seine Arbeit beendet löscht er seine Statuszeile aus der Listview. Ich bräuchte nun ein Event oder einen functionsaufruf der den anderen beiden Threads signalisiert das ein eintrag der Listview gelöscht wurde und sie nun auf eine andere Zeile der Listview zugreifen müssen. Meine erste Idee war eine globale Variable in den Threads die der Thread der seine Arbeit gerade beendet auf true setzt. Problem dabei ist nur welcher Thread setzt die Variable wieder zurück denn die anzahl der laufenden threads ist nicht auf 3 beschränkt sondern variabel. Ich hoffe jemand hat eine Idee zur Lösung des Problems :) Mfg Yannic |
Re: Globale Thread function ?
Da alle Threads syncronisiert auf die Listview zugreifen müssen kannst du für alle Threads die gleiche Methode verwenden und in dieser entscheidest du dann welche Zeile welcher Thread bekommt.
|
Re: Globale Thread function ?
Danke für die Antwort.
Ich sehe da aber gerade ein kleines problem. Die Threads können ja nicht mit parametern syncen. Momentan habe ich eine eigen Unit für die Threads. (ThreadUnit) und gesynct wird beispielsweise auf ThreadUnit.ShowStatus. Die Show Status greift dann auf die privaten Variablen des Threads zurück. Wenn ich die ShowStatus jetzt ins Main Form verschiebe und dann auch MainForm.ShowStatus synce kennt die MainForm.ShowStatus die private variablen des jeweiligen Threads doch garnicht, da ich sie nicht mit parametern übergeben kann oder ? Mfg Yannic |
Re: Globale Thread function ?
Meinst du sowas:
![]() |
Re: Globale Thread function ?
Hi,
genau das war der Denkanstoß ;) Danke funktioniert jetzt :) Mfg Yannic |
Re: Globale Thread function ?
Hi,
ich melde mich nochmal in diesem Thread, da das Problem hier im Prinzip noch reinpasst. Problem ist folgendes. Ich starte von der Mainform aus x Threads nach folgendes Schema:
Delphi-Quellcode:
Der Grobe Aufbau des Threads:MainForm: var IndyThread: TDownloadThread; .... IndyThread := TDownloadThread.Create(True); IndyThread.FreeOnTerminate := True; IndyThread.URL := LinkList.Items.Item[i].Caption; IndyThread.FilePath := DownloadPfad; IndyThread.RsUsername := frmOptions.edtRSUsername.Text; IndyThread.RsPassword := frmOptions.edtRSPassword.Text; IndyThread.Resume; IndyThread := TDownloadThread.Create(True); IndyThread.FreeOnTerminate := True; IndyThread.URL := LinkList.Items.Item[i].Caption; IndyThread.FilePath := DownloadPfad; IndyThread.RsUsername := frmOptions.edtRSUsername.Text; IndyThread.RsPassword := frmOptions.edtRSPassword.Text; IndyThread.Resume; ....
Delphi-Quellcode:
Nun möchte ich die thrads abbrechen. Das mache ich momentan indem ich eine Globale variable is_abort in der Thread Unit definiert habe und alle Threads im OnWork prüfen ob is_abort true oder false ist.
unit ThreadUnit;
interface uses Classes, SysUtils, Windows, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdException, ComCtrls; var is_abort: Boolean; type TWorkBeginEvent = procedure(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer) of object; TWorkEvent = procedure(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer) of object; TWorkEndEvent = procedure(ASender: TObject; AWorkMode: TWorkMode) of object; TDownloadThread = class(TThread) private { Private-Deklarationen } FURL: string; FID: string; FFMessage: string; FFilePath: string; FFileName: string; FWorkCountMax: Integer; FWorkCount: Integer; IdHTTPDownload: TIdHTTP; filestream: TFileStream; procedure ShowStatus; procedure ShowEnd; procedure Error; procedure Successful; procedure Abort; procedure FWorkBeginEvent(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer); procedure FWorkEvent(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer); procedure FWorkEndevent(ASender: TObject; AWorkMode: TWorkMode); public property URL: string read FURL write FURL; property FilePath: string read FFilePath write FFilePath; protected procedure Execute; override; end; implementation uses MainU, GlobalsU; { TDownloadThread } procedure TDownloadThread.Execute; begin IdHTTPDownload := TIdHTTP.Create(nil); is_abort := False; try IdHTTPDownload.OnWorkBegin := FWorkBeginEvent; IdHTTPDownload.OnWork := FWorkEvent; IdHTTPDownload.OnWorkEnd := FWorkEndevent; FFileName := SetFileName(FURL); FID := FFileName; filestream := TFileStream.Create(FFilePath + FFileName, fmCreate); try IdHTTPDownload.Get(FURL, filestream); except on E: Exception do begin FFMessage := E.message; Synchronize(Error); end; end; finally IdHTTPDownload.Free; filestream.Free; end; end; procedure TDownloadThread.FWorkBeginEvent(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer); begin FWorkCountMax := AWorkCountMax; Synchronize(ShowStatus); end; procedure TDownloadThread.FWorkEvent(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer); begin FWorkCount := AWorkCount; if is_abort then Synchronize(Abort); // Wenn is_abort dann Download abbrechen // Berechnen der Statuswerte Synchronize(ShowStatus); end; procedure TDownloadThread.FWorkEndevent(ASender: TObject; AWorkMode: TWorkMode); begin if not is_abort then begin Synchronize(ShowEnd); Synchronize(Successful); end; end; procedure TDownloadThread.ShowStatus; begin // Zugriff auf die Vcl der Mainform end; procedure TDownloadThread.Successful; begin // Zugriff auf die Vcl der Mainform end; procedure TDownloadThread.ShowEnd; begin // Zugriff auf die Vcl der Mainform end; procedure TDownloadThread.Error; begin // Zugriff auf die Vcl der Mainform end; procedure TDownloadThread.Abort; begin // Download abbrechen IdHTTPDownload.Disconnect; // Zugriff auf die Vcl der Mainform end; end. Im Prinzip funktioniert das auch. Ist allerdings nicht sonderlich schön wie ich finde (TDownloadThread.Abort;) wird auch mehrmals aufgerfufen, bevor das Disconnect wirklich gegriffen hat. Gibt es eine Möglichkeit das ganze nicht über eine Variable zu prüfen, sondern eine Procedure oder ein Event das ich von der Mainform aus aufrufen kann, welches dann in allen Threads aufgerufen wird ? Mfg Yannic |
Re: Globale Thread function ?
Nur eine Variable und immer wieder neue Instanzen darauf erzeugen die dann länger bestehen.. pfui.
Nimm eine odentliche Liste in der Du die Threads verwaltest, dann hast Du auch jederzeit Zugriff darauf. Grüsse, Dirk |
Re: Globale Thread function ?
Hi,
sorry für die Dumme Frage aber was verstehst du in diesem Fall unter einer Liste zum verwalten ? Das wäre natürlich optimal wenn ich auf alle Instanzen zugreifen könnte. Mfg Yannic |
Re: Globale Thread function ?
Ein "array of TDownloadThread" oder eine TList, damit Du eine Referenz auf jeden Thread behältst. Das Array bzw. die Liste kannst Du dann durchlaufen und jeden Thread nach Belieben manipulieren. Deine Variable "IndyThread" zeigt ja immer nur auf die zuletzt erstellte Instanz.
Grüsse, Dirk |
Re: Globale Thread function ?
Soweit funktioniert jetzt schonmal alles ganz gut. Danke dafür :)
Lässt sich noch irgendwie feststellen, ob threadarray[x] schon erzeugt wurde ? Momentan fange ich das über eine try except ab, das scheint mir aber nicht das optimum zu sein. Mfg Yannic |
Re: Globale Thread function ?
Vor Erstellung sauber auf nil setzen und auch sauber mit FreeAndNil() freigeben, dann kannst Du auf Assigned() prüfen.
Grüsse, Dirk |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz