|
Registriert seit: 19. Jan 2008 Ort: Brhv 97 Beiträge Delphi 10.2 Tokyo Professional |
#11
Wenn du in einem Thread "UpdateStatus" aufrufst wird das hier im Hauptthread (durch das Synchronize) aufgerufen.
Delphi-Quellcode:
Dabei greifst du auf die (globale) Variable "Ergebnisliste" zu. Wenn ein weiterer Thread aber gerade dabei ist in diese Ergebnisliste zu schreiben, kommt es zu Problemen.
Threads[Index] := TURLCheckerThread.Create(UrlList, CriticalSection,
procedure(Msg: string) begin RichEditLog.Lines.Add(Msg); {Ergebnis als String} RichEditLog.Lines.Add(ErgebnisListe.Text); {Ergebnis als StringList} ErgebnisListe.Clear; {Nicht vergessen, sonst wird die StringList immer weiter befüllt} end, @ShouldStop, ErgebnisListe); Lösung: Auch dort die CriticalSection benutzen. Des weiteren nutzt du 1 CriticalSection für 2 unterschiedliche Listen. Das funktioniert zwar, aber du sperrst immer 2 Listen, was das ganze verlangsamen kann. Lösung: 2 CriticalSections oder TMonior.Enter(Liste) verwenden. Nur als grobe Info. Kann ich einfach eine Zweite CriticalSection einbauen und gut ist? Die eine bleibt für FUrlList und eine zweite für FResultList ??? @himitsu Sorry, auf deinen Vorschlag gehe ich erst nicht ein, bin eh schon am Limit. Für heute reicht es mir, glaube ich. Hier noch meine Änderung, jetzt sollte je Thread eine Liste benutzt werden.
Delphi-Quellcode:
EDIT, erst jetzt gesehen, da stimmt noch etwas nicht. Es reicht für heute. Sonst kommt nur noch Misst dabei raus.
procedure ButtonStartClick(Sender: TObject);
procedure ButtonAbbruchClick(Sender: TObject); procedure ButtonWeiterClick(Sender: TObject); procedure ButtonEXITClick(Sender: TObject); private { Private-Deklarationen } CriticalSection : TCriticalSection; UrlList : TStringList; ErgebnisListe : TStringList; ActiveThreads : Int64; IdleJobs : Int64; JobsFinished : Int64; procedure UpdateLabelActiveThreads; procedure UpdateLabelJobs; procedure UpdateLabelFinished; public { Public-Deklarationen } end; var Form1 : TForm1; ShouldStop : Boolean = False; implementation {$R *.dfm} type TURLCheckerThread = class(TThread) private FUrlList : TStrings; FCriticalSection : TCriticalSection; FOnStatus : TProc<TstringList>; FShouldStop : PBoolean; protected procedure Execute; override; procedure UpdateStatus(const Msg: TstringList); public constructor Create(UrlList: TStrings; CriticalSection: TCriticalSection; OnStatus: TProc<TstringList>; ShouldStop: PBoolean); end; { TWorkerThread } constructor TURLCheckerThread.Create(UrlList: TStrings; CriticalSection: TCriticalSection; OnStatus: TProc<TstringList>; ShouldStop: PBoolean); begin inherited Create(False); FUrlList := UrlList; FCriticalSection := CriticalSection; FOnStatus := OnStatus; FShouldStop := ShouldStop; FreeOnTerminate := True; end; procedure TURLCheckerThread.UpdateStatus(const Msg: TstringList); begin if Assigned(FOnStatus) then TThread.Synchronize(TThread.Current, procedure begin FOnStatus(Msg); end); end; procedure TURLCheckerThread.Execute; var FResultList : TstringList; Url : string; Http : TIdHTTP; begin Http := TIdHTTP.Create(nil); try while not Terminated and not FShouldStop^ do begin Url := ''; FCriticalSection.Acquire; try if FUrlList.Count > 0 then begin Url := FUrlList[0]; FUrlList.Delete(0); end; finally FCriticalSection.Release; end; if Url = '' then Break; Sleep(Random(2000)); {Hier kommt später meine Aufgabe} FResultList := TStringList.Create; //--> Hier geändert Pro Job wird eine Liste erstellt und zerstört try try // Http.Head(Url); FCriticalSection.Acquire; {Keine Ahnung ob es richtig ist, habe aber rausgelesen dass man StringList auf jeden Fall mit CriticalSection absichern soll} try FResultList.Add('OK: ' + Url); {Ergebnis in StringList eintragen} FResultList.Add('Zweite Zeile'); {Ergebnis in StringList eintragen} FResultList.Add('Dritte Zeile'); {Ergebnis in StringList eintragen} finally FCriticalSection.Release; end; UpdateStatus(FResultList); except on E: Exception do begin FResultList.Add('FAIL: ' + Url + ' - ' + E.Message); UpdateStatus(FResultList); end; end; finally FreeAndNil(FResultList); //--> Hier geändert Pro Job wird eine Liste erstellt und zerstört end; TThread.Synchronize(nil, procedure begin Dec(Form1.IdleJobs); Form1.UpdateLabelJobs; Inc(Form1.JobsFinished); Form1.UpdateLabelFinished; end); end; finally FreeAndNil(FResultList); FreeAndNil(Http); TThread.Synchronize(nil, procedure begin Dec(Form1.ActiveThreads); Form1.UpdateLabelActiveThreads; end); end; end; procedure TForm1.ButtonStartClick(Sender: TObject); var Threads : array[0..99] of TURLCheckerThread; Index : Integer; begin if Assigned(CriticalSection) then FreeAndNil(CriticalSection); {Falls ich nach Cancel noch mal Start drücke statt Weiter} if Assigned(UrlList) then FreeAndNil(UrlList); {Falls ich nach Cancel noch mal Start drücke statt Weiter} UrlList := TStringList.Create; CriticalSection := TCriticalSection.Create; ShouldStop := False; for Index := 1 to 100 do begin URLList.Add('http://google.com/' + IntToStr(Index)); end; LabelJobs.Caption := '100'; LabelIdle.Caption := '100'; IdleJobs := 100; JobsFinished := 0; for Index := 1 to SpinEditThreads.Value do begin Threads[Index] := TURLCheckerThread.Create(UrlList, CriticalSection, procedure(Msg: TstringList) var ErgebnisListe : TStringList; begin RichEditLog.Lines.Add(Msg.Text); {Ergebnis als StringList} end, @ShouldStop); {Zähle aktive Threads} Inc(ActiveThreads); LabelActiveThreads.Caption := IntToStr(ActiveThreads); end; end; procedure TForm1.ButtonWeiterClick(Sender: TObject); var Threads : array[0..99] of TURLCheckerThread; Index : Integer; begin ShouldStop := False; for Index := 1 to SpinEditThreads.Value do begin Threads[Index] := TURLCheckerThread.Create(UrlList, CriticalSection, procedure(Msg: TstringList) begin RichEditLog.Lines.Add(Msg.Text); {Ergebnis als StringList} end, @ShouldStop); {Zähle aktive Threads} Inc(ActiveThreads); LabelActiveThreads.Caption := IntToStr(ActiveThreads); end; end; procedure TForm1.ButtonAbbruchClick(Sender: TObject); begin ShouldStop := True; end; procedure TForm1.ButtonEXITClick(Sender: TObject); begin ShouldStop := True; Close; end; procedure TForm1.UpdateLabelActiveThreads; begin LabelActiveThreads.Caption := IntToStr(ActiveThreads); end; procedure TForm1.UpdateLabelJobs; begin LabelIdle.Caption := IntToStr(IdleJobs); end; procedure TForm1.UpdateLabelFinished; begin LabelFinished.Caption := IntToStr(JobsFinished); end; Das Teil mag ich auch nicht, erstmal habe ich auch kein Plan wie ich es korrigieren/verbessern kann.
Delphi-Quellcode:
TThread.Synchronize(nil, procedure
begin Dec(Form1.ActiveThreads); Form1.UpdateLabelActiveThreads; end); Geändert von IMPEGA (Heute um 12:40 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |