Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Änderungen von Variablen synchronisieren (https://www.delphipraxis.net/167197-aenderungen-von-variablen-synchronisieren.html)

Breager 17. Mär 2012 09:58

Änderungen von Variablen synchronisieren
 
Hallo,

ich hoffe, der Titel ist treffend. Ich habe eine Variable vom Typ String, die sowohl innerhalb eines Threads als auch außerhalb des Threads verändert werden kann. Die Wahrscheinlichkeit ist wohl sehr gering, aber ich befürchte, dass es theoretisch zu Problemen kommen könnte, wenn ich versuche, den Wert dieser Variablen gleichzeitig innerhalb des Threads und außerhalb des Threads zu ändern.

Hier mein Lösungsversuch:
Delphi-Quellcode:
Var ThreadString:AnsiString;
    TreadString_Locked:Boolean;

//Innerhalb des Threads
Begin
...
 ThreadString_Locked:=True;
 ThreadString:='Neuer Wert';
 ThreadString_Locked:=False;
...
End;

//außerhalb des Threads:

Function SetThreadString(s:AnsiString):Boolean;
Var TimeOut:Integer;
Begin
 TimeOut:=0;
 Repeat
 IF not(ThreadString_Locked) then
    BEGIN
     ThreadString:=s;
     Result:=True;
    END ELSE
     Result:=False;

 Inc(TimeOut);
Until TimeOut>1000;
End;
Solange der Wert innerhalb des Threads durch die Variable ThreadString_Locked gesperrt ist, kann der Variablen außerhalb des Threads nichts zugewiesen werden.

Ist dieser Ansatz sinnvoll bzw., gibt es eine einfachere oder besser Lösung?

Gruß

Sir Rufo 17. Mär 2012 10:11

AW: Änderungen von Variablen synchronisieren
 
Jo, z.B. Delphi-Referenz durchsuchenTCriticalSection ;)

und auch mal hier schauen Hier im Forum suchenTCriticalSection

Aphton 17. Mär 2012 11:16

AW: Änderungen von Variablen synchronisieren
 
Apropos Timeout -> du hast da nen Vergleich mit 1000 gemacht, was evt. impliziert, dass du wirklich 1000 ms (1 sek) warten möchtest. Das ist aber nicht der Fall.. Das sind einfach 1000 Schleifendurchläufe; daher ist das auch abhängig von der Prozessorgeschwindigkeit. Verarbeitet dein Prozessor einen Schleifendurchgang in genau einer ms, dann würde das stimmen, nur ist das nicht der Fall. Diese Schleife ist binnen kürzester Zeit durchlaufen (<10ms?)

...nur ne Kleinigkeit ^^

himitsu 17. Mär 2012 12:47

AW: Änderungen von Variablen synchronisieren
 
Booleans sind nicht threadsicher, vorallem da sie nichtmal atomar änderbar sind, da die CPU mir kompletten Registern arbeitet und dann nur die Bytes raus ANDed und SCHIFTet. :stupid:
Die CPUs kennen da einen speziellen Befehl LOCK

z.B.
Delphi-Quellcode:
LOCK MOV [EAX], EDX
statt
Delphi-Quellcode:
MOV [EAX], EDX
.
Und die WinAPI kennt die Interlocked-Behle, wie MSDN-Library durchsuchenInterlockedExchange.


Deine "innere" Änderung von ThreadString ist nicht abgesichert, denn da wird nicht geprüft, ob der String gerade von SetThreadString verändert wird.

Gut, man könnte jetzt beide Zeiten absichern und dann äußere und inner Änderungen nur über dieses SetThreadString ausführen,
Delphi-Quellcode:
Function SetThreadString(s:AnsiString):Boolean;
Var TimeOut:Integer;
Begin
 TimeOut:=0;
 Repeat
   IF not(ThreadString_Locked) then
    BEGIN
     ThreadString_Locked:=True;
     ThreadString:=s;
     ThreadString_Locked:=False;
     Result:=True;
    END ELSE
     Result:=False;

 Inc(TimeOut);
Until TimeOut>1000;
End;
aber hier kann es immernoch vorkommen, daß mehrere Threads gleichzeitig durch das IF kommen und :=True setzen, da diese Beiden erst Recht nicht atomar sind.

Ich hatte letzens die CriticalSection über TryEnter und eine Schleife mit einem TimeOut versehn.
Schön ist das nicht unbedingt, aber es funktioniert wenigstens.

Breager 17. Mär 2012 17:50

AW: Änderungen von Variablen synchronisieren
 
Vielen Dank für Eure Antworten!

Mir brummt schon ganz schön der Schädel. Vielleicht warte ich doch lieber, bis der Thread beendet wurde ;-)

Brauche ich zum Lesen auch eine CriticalSection? Wird der Code innerhalb der CriticalSection in eine Warteschleife gelegt und später abgearbeitet oder einfach nicht ausgeführt/ignoriert? Letzteres wäre vorallem beim Lesen ungünstig.

Zitat:

Zitat von himitsu
Ich hatte letzens die CriticalSection über TryEnter und eine Schleife mit einem TimeOut versehn.

Danke. Im Grunde also das, was ich mit meinem Code erreichen möchte (ein Pollen sozusagen).

Bin gerade über TMultiReadExclusiveWriteSynchronizer gestolpert, was haltet ihr davon? Ich muss den Wert vorwiegend lesen.

Sir Rufo 17. Mär 2012 20:01

AW: Änderungen von Variablen synchronisieren
 
Eigentlich ist das mit der TCriticalSection sehr einfach.

Stell dir eine Kreuzung vor. Die beiden Straßen sind einmal der MainThread und der Thread den du laufen lässt. Die CriticalSection ist nun die Ampel, die dafür sorgt, dass über den Kreuzungspunkt (Zugriff auf die Variable) immer nur eine Fahrbahn (Thread) freigegeben ist.

Delphi-Quellcode:
TMyThread = class( TThread )
strict private
  FCS : TCriticalSection;
private
  FIntStr : string;
  procedure SetIntStr( const Value : string );
  function GetIntStr : string;
protected
  procedure Execute; override;
public
  property IntStr : string read GetIntStr write SetIntStr;
end;

...

procedure SetIntStr( const Value : string );
begin
  FCS.Enter; // Betreten der CS
  try
    FIntStr := Value;
  finally
    FCS.Leave; // Verlassen der CS
  end;
end;

function GetIntStr : string;
begin
  FCS.Enter; // Betreten der CS
  try
    Result := FIntStr;
  finally
    FCS.Leave; // Verlassen der CS
  end;
end;
Bei
Delphi-Quellcode:
FCS.Enter
wird solange gewartet, bis die CriticalSection frei ist und dann betreten.
Innerhalb eines Thread-Kontexts darf die CS sooft betreten werden, wie man möchte. Die CS sperrt ja nur gegen Zugriffe durch unterschiedliche Thread-Kontexte.

Die Getter und Setter der Eigenschaft kümmern sich nun darum, dass der Zugriff geregelt wird, egal aus welchem Thread-Kontext man darauf zugreift.
Aber ... innerhalb des Threads könnte man ja direkt auf
Delphi-Quellcode:
FIntStr
zugreifen, aber dieser Zugriff ist nicht abgesicht (über die CS), also sollte der Zugriff auch innerhalb des Threads über die Eigenschaft und nicht über das Feld erfolgen.
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
    ...
    // FIntStr := 'So nicht';
    IntStr := 'So geht das';
    ...
  end;
end;
end;
Der Vollständigkeit halber sei noch erwähnt, dass die Instanz von FCS natürlich von TMyThread im Constructor erzeugt und im Destructor wieder freigegeben werden sollte bzw. muss.

Breager 17. Mär 2012 20:53

AW: Änderungen von Variablen synchronisieren
 
Danke Sir Rufo :-D

Habs gerade selbst getestet und gesehen, dass alles schön sauber nacheinander abgearbeitet wird.
Ich benutze in meinem Programm eine TList, dessen Items ich jeweils einen Record zuweise. Ein Bestandteil dieses Records ist die String-Variable (in meinem Beispiel ThreadStrg).

Jedes Bearbeiten der Liste (Add, Insert, Delete, Exchange, Clear) im Hauptthread und natürlich das Ändern sowie das Lesen des Strings im Thread und im Hauptthread muss ich also einfach in die CriticalSection packen.
Zitat:

Zitat von Sir Rufo
Der Vollständigkeit halber sei noch erwähnt, dass die Instanz von FCS natürlich von TMyThread im Constructor erzeugt und im Destructor wieder freigegeben werden sollte bzw. muss.

Außerdem muss die Unit SyncObjs eingebunden werden.

Für meinen Fall ist es dann wahrscheinlich am sinnvollsten, die Instanz FCS zusammen mit TList zu erstellen und wieder freizugeben?

@Aphton: Danke für Deinen Hinweis. Das ist mir schon klar. Für ein zeitgebundenes Timeout würde ich etwas anders an die Sache rangehen.

himitsu 17. Mär 2012 22:56

AW: Änderungen von Variablen synchronisieren
 
Microsoft hat leider die Verwaltung der CS umgestllt.
In den Debuginfos der CS gibt es eigentlich ein Event-Objekt, an welches ich mich dranhängen wollte, um nicht pollen zu müssen, aber leider ist dort, zumindestens in Win7/Server2008/Server2011 immer nur "Nichts" (0) eingetragen. :cry:

In der Unit SyncObjs gibt es auch Objekte, welche ein TimeOut verwenden können.



PS: Deine 1000-Schleifendurchläufe dürften schneller sein, als die Speicherverwaltung eines Strings, was sich etwas ungünstig auswirken dürfte.

Breager 18. Mär 2012 00:46

AW: Änderungen von Variablen synchronisieren
 
Danke himitsu!

Das klingt nicht so gut :(

Hier mal ein Versuch, das ganze mit InterlockedExchange sicher zu machen:
Delphi-Quellcode:
Var ThreadString:AnsiString;
    ThreadString_Locked:Integer;
...
ThreadString_Locked:=Integer(False);
...

Function SetThreadString(S:AnsiString):Boolean;
Var TimeOut:Integer;
Begin
 TimeOut:=0;
 Repeat
  IF InterlockedExchange(ThreadString_Locked,Integer(True)) = 0 then
     BEGIN
      ThreadString:=S;
      InterlockedExchange(ThreadString_Locked,Integer(False));
      Result:=True;
     END ELSE
      Result:=False;
  Inc(TimeOut);
 Until (TimeOut>1000) OR Result;
End;
Das weitere Verarbeiten der Liste (Sortieren, etc.) findet nur im Mainthread statt. Hierbei müsste ich einfach überprüfen, ob der Thread aktiv ist oder ThreadString_Locked auf True gesetzt ist.

Mal noch eine generelle Frage: Solange ich den Wert einer globalen Variablen nur innerhalb "eines" Threads ändere, kann doch eigentlich nicht passieren, und beim Lesen doch sowieso nichts?

Sir Rufo 18. Mär 2012 01:17

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von Breager (Beitrag 1157123)
Mal noch eine generelle Frage: Solange ich den Wert einer globalen Variablen nur innerhalb "eines" Threads ändere, kann doch eigentlich nicht passieren, und beim Lesen doch sowieso nichts?

Wenn beide Threads nur lesend zugreifen, dann passiert IMHO nichts. Problematisch ist es wenn egal welcher Thread schreibend zugreift, dann geht von einem anderen Thread auch das Lesen in die Hose.

Ergo Lesen und Schreiben absichern.

Furtbichler 18. Mär 2012 08:48

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von Sir Rufo (Beitrag 1157108)
Aber ... innerhalb des Threads könnte man ja direkt auf
Delphi-Quellcode:
FIntStr
zugreifen, aber dieser Zugriff ist nicht abgesicht (über die CS), also sollte der Zugriff auch innerhalb des Threads über die Eigenschaft und nicht über das Feld erfolgen.

Oder man baut eine eigene Klasse dafür: TThreadsafeString, der gar nichts anderes erlaubt, als den Zugriff über die Property und damit über die CS.

Breager 18. Mär 2012 11:13

AW: Änderungen von Variablen synchronisieren
 
So, vielen Dank nochmal an alle. Ich habe nun alle wichtigen Operationen der TList (Add, Insert, Delete, Exchange, Clear) und natürlich das Umbenennen des Strings mit Hilfe von TCriticalSection in kritische Abschnitte gepackt. Die Performance ist nach wie vor gut.

Zitat:

Zitat von himitsu
Microsoft hat leider die Verwaltung der CS umgestllt.
In den Debuginfos der CS gibt es eigentlich ein Event-Objekt, an welches ich mich dranhängen wollte, um nicht pollen zu müssen, aber leider ist dort, zumindestens in Win7/Server2008/Server2011 immer nur "Nichts" (0) eingetragen.

Das kann ich im Moment leider nicht testen. Bin mir immer noch nicht sicher, ob ich nun pollen sollte oder nicht? Ist das vom System oder vom Compiler abhängig?
Delphi-Quellcode:
While not(FCS.TryEnter) do InfiniteLoop;
... tue irgendetwas
FSC.Leave

Sir Rufo 18. Mär 2012 11:23

AW: Änderungen von Variablen synchronisieren
 
Die Mühe bei der TList hättest du dir sparen können, wenn du einfach Delphi-Referenz durchsuchenTThreadList benutzen würdest :)

BTW: Du solltest immer mit einem Schutzblock arbeiten:
Delphi-Quellcode:
While not(FCS.TryEnter) do InfiniteLoop;
try
  ... tue irgendetwas
finally
  FSC.Leave;
end;
und auch das ist eigentlich völlig überflüssig, weil du hiermit genau das gleiche erreichst wie mit
Delphi-Quellcode:
FCS.Enter; // Wartet so lange, bis die CS betreten werden kann
try
  ... tue irgendetwas
finally
  FCS.Leave;
end;

Breager 18. Mär 2012 11:40

AW: Änderungen von Variablen synchronisieren
 
TThreadlist hatte ich auch bereits gefunden. Allerdings fehlt dort Insert und Exchange oder habe ich etwas übersehen? Gut, das könnte man im Notfall noch selbst implementieren.
Zitat:

Zitat von Sir Rufo
BTW: Du solltest immer mit einem Schutzblock arbeiten.

Ja, hast recht. Werde ich in Zukunft sofort einbauen.

EDIT: Das geht ja anscheinend doch. Muss ich mir nochmal gründlich unter die Lupe nehmen. Man lernt eben nie aus. Vielen Dank für den Hinweis.

himitsu 18. Mär 2012 12:31

AW: Änderungen von Variablen synchronisieren
 
Pollen ist hier leider die einzige Möglichkeit, wenn man ein TimeOut benötigt, also bei der CS.
Ansonsten müßte man auf Events (z.B. MSDN-Library durchsuchenSetEvent oder Delphi-Referenz durchsuchenTEvent) umsteigen.

Beim Pollen muß meventuell an aufpassen, daß man nicht die CPU hochtreibt.
Ich bei da Pausen in die Schleife, so mit je um die 20 Millisekunden.
Aber dort kann man sich unter umständen auch aussperren, wenn zwei/mehrere Threads in schneller Follge drauf zugreifen und zwischen 2 Zugriffen die Zeit kürzer ist, als die Pause.

Breager 19. Mär 2012 17:48

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von himitsu
Beim Pollen muß meventuell an aufpassen, daß man nicht die CPU hochtreibt.
Ich bei da Pausen in die Schleife, so mit je um die 20 Millisekunden.
Aber dort kann man sich unter umständen auch aussperren, wenn zwei/mehrere Threads in schneller Follge drauf zugreifen und zwischen 2 Zugriffen die Zeit kürzer ist, als die Pause.

Da reicht sogar schon eine Millisekunde aus ;-) Hatte ich die letzten Tage mal selbst getestet. Hatte das ganz falsch verstanden. Dachte, das Enter wartet genauso wenig wie das TryEnter. Habs jetzt erstmal ohne Pollen umgesetzt.

Und zwar habe ich mir eine einfache threadsichere Klasse (mit CriticalSections) gebaut, die sich um alles kümmert. Ich weiss, dafür gibts die ThreadList, die fand ich von der Schreibarbeit jedoch auch nicht wesentlich angenehmer. In meiner Klasse überlasse ich es dem Benutzer, ob er die Liste manuell sperren möchte oder ob dies automatisch geschieht.
Delphi-Quellcode:
interface
Uses Classes, SysUtils, SyncObjs;
type

  TMyList = class
    private
      MyList:TList;
      FCS : TCriticalSection;
      MustLock:Boolean; //Liste muss gesperrt werden
      Procedure Lock; //Internes Sperren
      Procedure Unlock; //Internes Freigeben

    public
      Procedure Locklist; //Manuell sperren
      Procedure Unlocklist; //Manuell freigeben

      Constructor Create;
      Destructor Destroy;
      Function Count:Integer;
      ...
   end;

implementation

Constructor TMyList.Create;
Begin
  MyList:=TList.Create;
  FCS := TCriticalSection.Create;
  MustLock:=True; //Liste muss automatisch gesperrt werden
End;

Procedure TMyList.Lock;
Begin
IF MustLock then
   FCS.Enter;
End;

procedure TMyList.Unlock;
begin
IF MustLock then
   FCS.Release;
end;


Procedure TMyList.Locklist;
Begin
 FCS.Enter;
 MustLock:=False; //Liste muss später NICHT automatisch gesperrt werden
End;

Procedure TMyList.Unlocklist; //EDIT: Reihenfolge der Codezeilen wurde getauscht
Begin
  MustLock:=True; //Liste muss später automatisch gesperrt werden
  FCS.Release;
End;

Function TMyList.Count:Integer;
Begin
 lock;
 try
  Result:=MyList.Count;
 finally
  unlock;
 end;
End;
Der Vorteil hierbei ist, dass man bei Bedarf einen größeren Code-Block sperren kann, ansonsten muss ich mich um nichts kümmern.

Mal noch ne letzte Frage, wenn man in einer Schleife mehrere Items aus der Liste löscht, ist es dann besser, die komplette Schleife zu sprerren oder nur die einzelnen Delete?

mjustin 19. Mär 2012 17:58

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von Breager (Beitrag 1157417)

Delphi-Quellcode:

Procedure TMyList.Unlocklist;
Begin
  FCS.Release;
  MustLock:=True; //Liste muss später automatisch gesperrt werden
End;

Die beiden Zeilen würde ich sicherheitshalber tauschen:

Delphi-Quellcode:

Procedure TMyList.Unlocklist;
Begin
  MustLock:=True; //Liste muss später automatisch gesperrt werden
  FCS.Release; // erst jetzt darf ein anderer Thread an die Liste
End;

Breager 19. Mär 2012 18:06

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von mjustin
Die beiden Zeilen würde ich sicherheitshalber tauschen

Jo, danke. Hast recht, vertauscht ist besser (sicherer)!

Sir Rufo 19. Mär 2012 20:06

AW: Änderungen von Variablen synchronisieren
 
Erklär doch mal, wofür du das MustLock in LockList und UnlockList jeweils veränderst.
Das macht in meinen Augen keinen Sinn.

Sir Rufo 19. Mär 2012 20:08

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von Breager (Beitrag 1157417)
Mal noch ne letzte Frage, wenn man in einer Schleife mehrere Items aus der Liste löscht, ist es dann besser, die komplette Schleife zu sprerren oder nur die einzelnen Delete?

Das kommt darauf an, wie lange das jeweils dauert und inwieweit das aus Konsistenzgründen erforderlich sein muss.

Im Allgemeinen gilt, dass die CS sobald als möglich wieder freigegeben wird.

Breager 19. Mär 2012 21:53

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von Sir Rufo
Erklär doch mal, wofür du das MustLock in LockList und UnlockList jeweils veränderst. Das macht in meinen Augen keinen Sinn.

Wenn ich die CriticalSection über TMyList.Locklist starte, würde z.B. innerhalb von TMyList.Count ein erneuter Versuch, die CriticalSecion zu starten eine Ausführung des Codes in TMyList.Count blockieren.

Aus diesem Grund setze ich bei TMyList.Locklist MustLock:=False. Das bedeutet, dass ich z.B. innerhalb von Count keine CriticalSection mehr starten muss, da schon aktiv
Delphi-Quellcode:
IF MustLock then Lock
Also wird der Code in Count ausgeführt.

Sir Rufo 19. Mär 2012 22:29

AW: Änderungen von Variablen synchronisieren
 
Ja, sowas hatte ich mir gedacht :)

Aber das ist überflüssig und verkompliziert die Sache unnötig.

Eine CriticalSection sorgt dafür, das innerhalb selbiger nur ein ThreadKontext aktiv ist.
Innerhalb dieses ThreadKontextes kann eine CS aber beliebig oft betreten werden.
Die CS muss aber auch genauso oft wieder verlassen werden damit diese wieder frei für einen anderen ThreadKontext ist.
Delphi-Quellcode:
FCS.Enter;
FCS.Enter;
  TuWas;
FCS.Leave;
FCS.Leave;
Diese Konstrukt funktioniert problemlos, denn wenn die CS betreten werden kann, dann funktioniert auch das zweite Betreten.

Breager 19. Mär 2012 22:40

AW: Änderungen von Variablen synchronisieren
 
Alles klar :thumb: Danke, man lernt eben nie aus. Das Thema Threads wird mir noch die ein oder andere schlaflose Nacht bescheren (absolutes Neuland für mich) :roll:

himitsu 19. Mär 2012 22:54

AW: Änderungen von Variablen synchronisieren
 
Und das Try-Finally nicht vergessen, denn die CS muß eben unbedingt genau so oft verlassen/freigegeben werden, wie sie betreten/gesperrt wurde.

Breager 20. Mär 2012 00:16

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von himitsu
Und das Try-Finally nicht vergessen, denn die CS muß eben unbedingt genau so oft verlassen/freigegeben werden, wie sie betreten/gesperrt wurde.

Ja, das habe ich jetzt konsequent in jeder Function und Procedure, wie beim Beispiel von Count, eingebaut:
Delphi-Quellcode:
Function TMyList.Count:Integer;
Begin
 lock;
 try
  Result:=MyList.Count;
 finally
  unlock;
 end;
End;

Furtbichler 20. Mär 2012 06:27

AW: Änderungen von Variablen synchronisieren
 
Und das 'lock' bzw. 'unlock' sieht wie aus?

Blup 20. Mär 2012 07:21

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von Breager (Beitrag 1157417)
Delphi-Quellcode:
Procedure TMyList.Lock;
Begin
IF MustLock then
   FCS.Enter;
End;

procedure TMyList.Unlock;
begin
IF MustLock then
   FCS.Release;
end;


Procedure TMyList.Locklist;
Begin
 FCS.Enter;
 MustLock:=False; //Liste muss später NICHT automatisch gesperrt werden
End;

Procedure TMyList.Unlocklist; //EDIT: Reihenfolge der Codezeilen wurde getauscht
Begin
  MustLock:=True; //Liste muss später automatisch gesperrt werden
  FCS.Release;
End;

Wenn Thread1 Locklist aufgerufen hat und die Liste bearbeitet, kann Thread2 im Lock am FCS.Enter vorbei und die Liste ebenfalls zur gleichen Zeit bearbeiten.
:stupid: :pale: :oops:

himitsu 20. Mär 2012 07:46

AW: Änderungen von Variablen synchronisieren
 
Wozu das MustLock?

Erstmal das von Blup Genannte
und wenn sich zwischen Lock und Unlock das MustLock ändert, dann stimmt die Anzahl auch nicht mehr.


Im Prinzip ist das LockList/UnlockList umsonst, außerdem fehleranfällig und Lock/Unlock alleine reicht auch schon aus.

Breager 20. Mär 2012 17:11

AW: Änderungen von Variablen synchronisieren
 
Zitat:

Zitat von himitsu
Im Prinzip ist das LockList/UnlockList umsonst, außerdem fehleranfällig und Lock/Unlock alleine reicht auch schon aus.

Der Gedanke dahinter war, dass ich bei Bedarf Codeabschnitte einschließen kann.
Delphi-Quellcode:
MyList.Locklist;
Dateiinfo:=Leseausdatei(MyList.Item[5].FileName); //Leseausdatei ist kein Bestandteil der Klasse
//Was passiert, wenn während der Leseausdatei Function gleichzeitig das MyList.Item[5] über MyList.Delete(5) gelöscht wird.
Mylist.Item[5].Daten:=Dateiinfo; //Daten werden in falschen Item gespeichert.
MyList.LockList;
Sir Rufo hat mich schon darauf hingewiesen, dass das Mustlock überflüssig ist.

EDIT:
Zitat:

Zitat von himitsu
und wenn sich zwischen Lock und Unlock das MustLock ändert, dann stimmt die Anzahl auch nicht mehr.

Mustlock kann doch garnicht geändert werden, da Private

himitsu 20. Mär 2012 17:13

AW: Änderungen von Variablen synchronisieren
 
Das geht ja dennoch.
Delphi-Quellcode:
MyList.Lock;
try
  Dateiinfo:=Leseausdatei(MyList.Item[5].FileName); //Leseausdatei ist kein Bestandteil der Klasse
  //Was passiert, wenn während der Leseausdatei Function gleichzeitig das MyList.Item[5] über MyList.Delete(5) gelöscht wird.
  Mylist.Item[5].Daten:=Dateiinfo; //Daten werden in falschen Item gespeichert.
finally
  MyList.Unlock;
end;
Wenn du Mustlock entfernst, wirst du bemerken, daß Lock=LickList und Unlock=UnlockList.

Breager 20. Mär 2012 17:17

AW: Änderungen von Variablen synchronisieren
 
Ach so hast Du gemeint. Jo, da hast Du natürlich recht. :)
Zitat:

Zitat von blub
Wenn Thread1 Locklist aufgerufen hat und die Liste bearbeitet, kann Thread2 im Lock am FCS.Enter vorbei und die Liste ebenfalls zur gleichen Zeit bearbeiten.

Danke für den Hinweis. Wie schon geschrieben: Threads sind absolutes Neuland für mich. Muss mehr querdenken.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:53 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz