Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Prüfen ob TStrings gerade geupdated wird (https://www.delphipraxis.net/111117-pruefen-ob-tstrings-gerade-geupdated-wird.html)

Krümelmonster 29. Mär 2008 21:33


Prüfen ob TStrings gerade geupdated wird
 
Hallo zusammen,
Hat jemand eine Ahnung wie man prüfen kann ob ein TStrings gerade geupdated wird :?:

Ich hab den JclFileEnumerator und möchte dann am Ende des Updates die ListBox nochmal durchgehen um dann nur die Dateinamen anzeigen zu lassen.
Der JclFileEnumerator startet nähmlich einen Thread und so kann ich nicht einfach nach dem Aufruf FillList die ListBox sofort durchgehen.

Muetze1 29. Mär 2008 22:41

Re: Prüfen ob TStrings gerade geupdated wird
 
Da TStrings nur die abstrakte Basisklasse ist, wirst du somit niemals eine solche Instanz haben. Aber wenn z.B. TStringList instanziiert wird, dann kannst du deren OnChange Ereignis verknüppern & nutzen. Aber: ich bezweifle das die JCL Leute diese Möglichkeit beachtet haben, denn: Wenn du dich da ranhängst, dann würdest du von dem Thread aus aufgerufen werden (selbst wenn die intern Begin/EndUpdate nutzen, dann halt nur zum Ende), und somit müsstest du dich synchronisieren. Die JVL Leute haben das im Thread bestimmt nicht beachtet, weil sonst würde der Thread nichts nützen...

Schwedenbitter 8. Feb 2010 11:12

Re: Prüfen ob TStrings gerade geupdated wird
 
Ich wollte kein neues Thema aufmachen, da die Überschrift m.E. wie die sprichwörtliche Faust aufs Auge passt:

Ich benutze eine TStringList in einer Unit, um sie von meinem Hauptprogramm mit Dateinamen zu bestücken. Dann reagiere ich auf das Ereichnis OnChange und verarbeite die Dateinamen. Das funktioniert soweit super.

Nur sehe ich leider mehrere Probleme.
Innerhalb meiner Ereignisbehandlungsroutine gehe ich alle Einträge mittels
Delphi-Quellcode:
While Count > 0 Do
Begin
  S:=Strings[0];
  If S = ...
  // Verarbeiten der Einträge
  Delete(0);
End;
durch.
Wenn nun während der Verarbeitung weitere Einträge in der Liste hinzukommen, dann werden die mit abgearbeitet, weil dann Count wieder erhöht wird. Es wäre dann sinnlos und problematisch, wenn sich dann 2 Instanzen der Ereignisbehandlungsroutine in die Quere kämen. Meine Idee sah dann zunächst so aus:
Delphi-Quellcode:
If Laueft Then Exit; // nur eine Instanz laufen lassen
Laeuft:=True;
While Count > 0 Do
Begin
  S:=Strings[0];
  If S = ...
  // Verarbeiten der Einträge
  Delete(0);
End;
Laeuft:=False;
Aber ich hätte dann ein Problem, wenn meine Ereignisbehandlung exakt zwischen dem End; und dem Laeuft:=False; steht, während weitere Einträge hinzukommen. Der erneute Aufruf würde wegen des Zustandes von Laeuft sofort beendet (Then Exit;), meine neuen Einträge werden aber nicht mehr abgearbeitet, weil While Count > 0 Do ... schon vollständig beendet war.
Ich hoffe, Ihr könnte mein Problem nachvollziehen.

Case Nachvollziehen Of :lol:
Nein : Bitte nachfragen;
Ja : Wie kann ich das Dilemma lösen?
End;

Danke, Alex

himitsu 8. Feb 2010 11:22

Re: Prüfen ob TStrings gerade geupdated wird
 
Delphi-Quellcode:
While true Do
Begin
  // Zugriff auf String blockieren
  Try
    If Count > 0 Then
    Begin
      S:=Strings[0];
      Delete(0);
    End
    Else
      S := '';
  Finally
    // Zugriff auf String freigeben
  End;
  If S <> '' Then
  Begin
    // Verarbeiten der Einträge
  End Break;
End;

Oder du verwendest direkt eine Queue, welche für sowas ausgelegt wurde.
z.B. http://www.delphipraxis.net/internal...t.php?t=167796

Reinhard Kern 8. Feb 2010 12:20

Re: Prüfen ob TStrings gerade geupdated wird
 
Zitat:

Zitat von Schwedenbitter
Aber ich hätte dann ein Problem, wenn meine Ereignisbehandlung exakt zwischen dem End; und dem Laeuft:=False; steht, während weitere Einträge hinzukommen.

Du kannst es ja mal so oder ähnlich probieren:
Delphi-Quellcode:
While not done Do
Begin
  S:=Strings[0];
  If S = ...
  // Verarbeiten der Einträge
  EnterCriticalSection (ms);
  Delete(0);
  done := count = 0;
  if done then Laeuft := false;
  LeaveCriticalSection (ms);
End;
Gruss Reinhard

Schwedenbitter 8. Feb 2010 12:32

Re: Prüfen ob TStrings gerade geupdated wird
 
[edit]Danke Reinhard! -> zu lange geschrieben![/edit]

Hallo und Danke himitsu!

Die Idee dahinter habe ich verstanden. Insbesondere While True Do und Break; sind klar. Man nimmt immer geschützt den ersten Eintrag und verarbeitet den. Ist nichts mehr da, dann wir abgebrochen.

Leider weiß ich aber nicht, wie ich
Delphi-Quellcode:
  // Zugriff auf String blockieren
und
Delphi-Quellcode:
  // Zugriff auf String freigeben
kann.

Außerdem habe ich dann ein Problem, wie ich das im "Lieferanten" lösen kann. Dort mache ich es im Moment so:
Delphi-Quellcode:
If NeuerStr <> '' Then
  WorkFiles.Text:=WorkFiles.Text + NeuerStr;
Wobei NeuerStr seinerseits vom Typ TStringList.Text ist. Also müsste ich das dann ungefähr so machen?
Delphi-Quellcode:
Repeat
Until ...; // Zugriff auf String freigegeben
If NeuerStr <> '' Then
  WorkFiles.Text:=WorkFiles.Text + NeuerStr;
Wie frage ich das wiederum ab? Da ich TStringList.Text über eine TCP/IP-Verbindung bekomme, könnte ich - falls das Sperren nur über die Functionen Add(), AddStrings() oder Append() geht - maximal mit einer temporären TStringList arbeiten.

Fragen über Fragen! Aber ich wollte es gern sauber mit meinen bescheidenen Programmierkenntnissen lösen.

Gruß, Alex

himitsu 8. Feb 2010 12:46

Re: Prüfen ob TStrings gerade geupdated wird
 
Zitat:

Zitat von Schwedenbitter
Leider weiß ich aber nicht, wie ich...

Am Einfachsten ist da wohl eine CriticalSection.


Delphi-Quellcode:
// ab D2006/TDE

// einen Generic-Stack vom Typ String erzeugen
var MyQueue: TGenStack<String>;

MyQueue := TGenStack<String>.Create;



// String hinten anhängen
MyQueue.Push(S);

// ältesten String vorne rausholen
While MyQueue.UnShift(S) do

{***** oder *****}

// String vorne einzufügen
MyQueue.Shift(S);

// ältesten String hingen rausholen
While MyQueue.Pop(S) do


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:27 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-2025 by Thomas Breitkreuz