Multitasking die 1.: CriticalSection
Multitasking die 1.: CriticalSection
Hi allseits,
ich beziehe mich auf das Beispielprojekt examples\waitforexample1.
in der Prozedur TBaseThread.Log setzt der Programmierer eine CriticalSection ein. Er muss das m.E. machen, weil er den Text, den er anhängen möchte, erst in einen String in Form1 (MsgText) schreibt, den er dann erst per Form1.AddMessage hinzufügt. Damit der String sicher ankommt, muss die Code-Sequenz die ihn setzt und dann dem Memo hinzufügt geschützt werden. So weit, so klar.
Ich bin mir gerade unsicher, ob das nur eine Demo ist, oder ob es gute Gründe gibt, warum das generell besser so gemacht werden soll. Immerhin hätte er Form1.Addmessage ja auch so schreiben können, dass er den String als Parameter übergibt, und damit m.E. das Problem nicht gehabt und die CriticalSection nicht gebraucht. Ich hätte es so gemacht, ohne eine Sekunde darüber nachzudenken, diese m.E. (in der Demo) unnütze MsgText Variable einzuführen, mit der ich mir dann Race Probleme zwischen den Threads einhandle, die ich mit der CriticalSection wieder wegbekommen muss.
Ist das also nur der Demo halber so programmiert, oder hatte der Autor der Demo einen guten Grund, über die Zwischenvariable zu gehen statt Form1.AddMessage bzw. sogar Form1.Memo.Add direkt zu bemühen?
Thnx, Armin.
ich beziehe mich auf das Beispielprojekt examples\waitforexample1.
in der Prozedur TBaseThread.Log setzt der Programmierer eine CriticalSection ein. Er muss das m.E. machen, weil er den Text, den er anhängen möchte, erst in einen String in Form1 (MsgText) schreibt, den er dann erst per Form1.AddMessage hinzufügt. Damit der String sicher ankommt, muss die Code-Sequenz die ihn setzt und dann dem Memo hinzufügt geschützt werden. So weit, so klar.
Ich bin mir gerade unsicher, ob das nur eine Demo ist, oder ob es gute Gründe gibt, warum das generell besser so gemacht werden soll. Immerhin hätte er Form1.Addmessage ja auch so schreiben können, dass er den String als Parameter übergibt, und damit m.E. das Problem nicht gehabt und die CriticalSection nicht gebraucht. Ich hätte es so gemacht, ohne eine Sekunde darüber nachzudenken, diese m.E. (in der Demo) unnütze MsgText Variable einzuführen, mit der ich mir dann Race Probleme zwischen den Threads einhandle, die ich mit der CriticalSection wieder wegbekommen muss.
Ist das also nur der Demo halber so programmiert, oder hatte der Autor der Demo einen guten Grund, über die Zwischenvariable zu gehen statt Form1.AddMessage bzw. sogar Form1.Memo.Add direkt zu bemühen?
Thnx, Armin.
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
GUI-relevante Komponenten (z.B. Form....) dürfen in WorkerThreads nicht angepackt werden.
-Michael
-Michael
Re: Multitasking die 1.: CriticalSection
Danke für die Antwort! Und gleich tauchen weitere Fragen auf.mschnell hat geschrieben:GUI-relevante Komponenten (z.B. Form....) dürfen in WorkerThreads nicht angepackt werden.
-Michael
Nur um des Lernens und Verstehens willen, warum nicht, und was passiert, wenn man es trotzdem tut?
Ich kenne den Effekt, dass direkte Zugriffe auf GUI Elemente keine (sofortige) Wirkung zeigen, so lange man nicht noch einen Application.Processmessages nachschiebt ... aus Threads heraus ist das also auch keine Option mehr?
Bisher arbeite ich gerne mit Synchronize. Ich hätte also auch sowas machen können?
Code: Alles auswählen
Synchronize(Memo1.Lines.Add(S));
Armin.
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
Aktivitäten (Funktionen, Properties) bei GUI Komponenten können das angebundene Widget-Set im Betriebssystem aufrufen und das ist nicht threadfest. Das Widget-Set in einem anderen Thread aufzurufen kann zu beliebigen Ergebnissen führen inklusive Total-Absturz des Programms.Nimral hat geschrieben:warum nicht, und was passiert, wenn man es trotzdem tut?
Genau dafür gibt es TThread.Synchronize (wenn der Worker-Thread warten soll, bis die (GUI-) Aktivitäten im Main Thread beendet sind) und TThread.Queue (wenn der Worker Thread parallel weiter laufen soll, was z.B. in diesem Fall, wenn nur einfach etwas in der GUI angezeigt werden soll, ideal ist).Nimral hat geschrieben:Bisher arbeite ich gerne mit Synchronize. Ich hätte also auch sowas machen können?
Strings arbeiten (anders als Klassen) mit einem threadfesten Reference-Counting. Bei Synchronize wird das sicher klappen, weil der String ja erst aus dem Fokus gerät, wenn die Mainthread-Aktivität fertig ist. Bei Queue darf man es nicht so machen. Einerseits bin ich nicht sicher, ob das Reference counting dann korrekt funktioniert und andererseit kann der Worker-Thread den String ja auch neu beschreiben, bevor der Mainthread ihn ausgegeben hat. Da sollte man eine TThreadlist mit allokierten Speicherblöcken verwenden, oder eine TStringlist, die man in eine Critical Section packt.Nimral hat geschrieben:[wie wird sicher gestellt, dass S dann überhaupt noch existiert?
-Michael
Zuletzt geändert von mschnell am Do 23. Jan 2020, 10:41, insgesamt 1-mal geändert.
- af0815
- Lazarusforum e. V.
- Beiträge: 6766
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Multitasking die 1.: CriticalSection
Bei gtk2 erhält man unter Umständen kryptische Fehlermeldungen, das Handels oder Objekte ungültig sind. Ist mir unlängst passiert, da ich bei einem Callback einer Komponente übersehen habe das da ein Threadwechsel vorgekommen ist. Erst wie ich das Programm aus der Kommandozeile gestartet habe, ist mir die Fehlermeldung aufgefallen.mschnell hat geschrieben:Aktivitäten (Funktionen, Proerties) bei GUI Komponenten können das angebundene Widget-Set im Betriebssystem aufrufen und das ist nicht threadfest. Das Widget-Set in einem anderen Thread aufzurufen kann zu beliebigen Ergebnissen führen inklusive Total-Absturz des Programms.Nimral hat geschrieben:warum nicht, und was passiert, wenn man es trotzdem tut?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
Re: Multitasking die 1.: CriticalSection
Hi Michael,
danke für die Klarstellungen, Du hast mir sehr weiter geholfen bei meinem aktuellen Projekt. An sich läuft es, aber ich hab noch ein paar Tage übrig im Budget und überlege, ob ich den Code nicht noch verbessern kann, möge es dem nächsten Projekt zugute kommen.
Was mich z.B. derzeit am meisten stört ist, dass, egal wie ich mit Synchronize, Queue oder Events umgehe, immer der Worker-Thread direkte Verweise auf entweder die GUI oder die Threads welche sonst noch was von ihm wollen könnten, beinhalten muss. Noch schöner (wenigstens auf dem Papier) wäre für meine Anwendung eine Architektur, bei welcher ein Worker-Thread, wenn er ein brauchbares Ergebnis hat (einen Messwert empfangen und ggf bearbeitet), diesen einfach irgendwie in die Luft katapultiert in Form einer "Message", und alle anderen Threads, die sich dafür interessieren, können damit machen was sie wollen. Das Messgerät ist ja nicht wirklich interessiert daran, ob seine Messwerte überhaupt von jemandem ausgewertet werden, und andererseits wäre das auch effizient, weil man so mit einer einzigen Message beliebig viele Threads mit einem Messwert versorgen könnte. Da alle Messgeräte ausschließlich relativ kleine Zahlen- oder kurze Status-Strings liefern, könnte der Mess-bzw. Statuswert als "Payload" direkt an der Message hängen.
Ich lese mich deshalb derzeit auch in Kommandos ein, die "Messages" auswerfen, also Sendmessage, Postmessage und Konsorten. Aber das ist eine andere Baustelle.
HG aus Bayern,
Armin.
danke für die Klarstellungen, Du hast mir sehr weiter geholfen bei meinem aktuellen Projekt. An sich läuft es, aber ich hab noch ein paar Tage übrig im Budget und überlege, ob ich den Code nicht noch verbessern kann, möge es dem nächsten Projekt zugute kommen.
Was mich z.B. derzeit am meisten stört ist, dass, egal wie ich mit Synchronize, Queue oder Events umgehe, immer der Worker-Thread direkte Verweise auf entweder die GUI oder die Threads welche sonst noch was von ihm wollen könnten, beinhalten muss. Noch schöner (wenigstens auf dem Papier) wäre für meine Anwendung eine Architektur, bei welcher ein Worker-Thread, wenn er ein brauchbares Ergebnis hat (einen Messwert empfangen und ggf bearbeitet), diesen einfach irgendwie in die Luft katapultiert in Form einer "Message", und alle anderen Threads, die sich dafür interessieren, können damit machen was sie wollen. Das Messgerät ist ja nicht wirklich interessiert daran, ob seine Messwerte überhaupt von jemandem ausgewertet werden, und andererseits wäre das auch effizient, weil man so mit einer einzigen Message beliebig viele Threads mit einem Messwert versorgen könnte. Da alle Messgeräte ausschließlich relativ kleine Zahlen- oder kurze Status-Strings liefern, könnte der Mess-bzw. Statuswert als "Payload" direkt an der Message hängen.
Ich lese mich deshalb derzeit auch in Kommandos ein, die "Messages" auswerfen, also Sendmessage, Postmessage und Konsorten. Aber das ist eine andere Baustelle.
HG aus Bayern,
Armin.
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
Ich mache das meistens mit (von mir so genannten) "Kommunikations-Objekten".
Ich definiere eine Klasse, die die Daten, die ich vom WorkerThread zum Mainthread senden will enthält (z.B. "TransportObject").
Außerdem enthält die Klasse eine Procedur z.B. "Transport".
im WorkerThread mache ich dann
Danach wird die Vatiable Transport nie wieder verwendet (!!!).
TransportObject.Transport gibt in entsprechender Form einen im Workerthread gesammelten Datensatz aus und räumt wenn nötig die in TransportObjekt enthaltenen Datenstrukturen auf. am Schluss steht einfach
Und das Transportobjekt gibt sich selber frei.
Also wird TransportObjekt.Transport im Mainthread laufen und kann da z.B. Prozeduren oder properties aufrufen und mit Daten versorgen.
Wenn Du die in "Transport" verwendeten Mainthread-relevanten Klassen (oder auch das Tansport-Objekt selber) nicht direkt im Thread definieren willst, kannst Du ja Deiner "TMyThread" Klasse entsprechende Properties geben, die Du im Mainthread-Umfeld nach Kreieren der MyThread Instanz entsprechende Objekte und Callback-Funktionen (z.B. DoTransportCreate) zuweist, die im Thread-Umfeld dann verwendet werden können.
-Michael
Ich definiere eine Klasse, die die Daten, die ich vom WorkerThread zum Mainthread senden will enthält (z.B. "TransportObject").
Außerdem enthält die Klasse eine Procedur z.B. "Transport".
im WorkerThread mache ich dann
Code: Alles auswählen
Transport := TransportObject.Create;
Transport.Datenxyz := ......;
....
MyThread.Queue(TransportObjekt.Transport);
TransportObject.Transport gibt in entsprechender Form einen im Workerthread gesammelten Datensatz aus und räumt wenn nötig die in TransportObjekt enthaltenen Datenstrukturen auf. am Schluss steht einfach
Code: Alles auswählen
free; // letzte Anweisung !!!
end; // Transport
Also wird TransportObjekt.Transport im Mainthread laufen und kann da z.B. Prozeduren oder properties aufrufen und mit Daten versorgen.
Wenn Du die in "Transport" verwendeten Mainthread-relevanten Klassen (oder auch das Tansport-Objekt selber) nicht direkt im Thread definieren willst, kannst Du ja Deiner "TMyThread" Klasse entsprechende Properties geben, die Du im Mainthread-Umfeld nach Kreieren der MyThread Instanz entsprechende Objekte und Callback-Funktionen (z.B. DoTransportCreate) zuweist, die im Thread-Umfeld dann verwendet werden können.
-Michael
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
Die Message Sachen sind ein "Relikt" aus Windows.Nimral hat geschrieben: Ich lese mich deshalb derzeit auch in Kommandos ein, die "Messages" auswerfen, also Sendmessage, Postmessage und Konsorten. Aber das ist eine andere Baustelle.
Da fpc aber auf vielen Betriebssystemen läuft, braucht man es nicht. FPC enthält entsprechende "allgemeine" Funktionalitäten im "Sprachumfang".
"Message", "Procedure message", etc verwendet 1:1 die Windows API, wenn das Programm auf Windows läuft und in der Library realisierte Workalikes, wenn das Programm auf einem anderen Betriebbssystem läuft.
Deshalb würde ich Messsage ertc nur verwenden , wenn ich weiß dass das Programm auf Windows laufen wird und spezielle Windows Funktionalität genutzt werden soll.
-Michael
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Multitasking die 1.: CriticalSection
Strings sind nicht Thread Sicher. Beispiel:mschnell hat geschrieben:Strings arbeiten (anders als Klassen) mit einem threadfesten Reference-Counting. Bei Synchronize wird das sicher klappen, weil der String ja erst aus dem Fokus gerät, wenn die Mainthread-Aktivität fertig ist. Bei Queue darf man es nicht so machen. Einerseits bin ich nicht sicher, ob das Reference counting dann korrekt funktioniert und andererseit kann der Worker-Thread den String ja auch neu beschreiben, bevor der Mainthread ihn ausgegeben hat. Da sollte man eine TThreadlist mit allokierten Speicherblöcken verwenden, oder eine TStringlist, die man in eine Critical Section packt.
-Michael
Code: Alles auswählen
program Project1;
{$mode objfpc}{$H+}
uses classes;
var s: String;
type
{ T }
T = class(TThread)
protected
procedure Execute; override;
end;
{ T }
procedure T.Execute;
var
i: Integer;
begin
for i:=0 to 1000000 do
begin
if length(s) > 100 then s := '';
s := s + 'a';
end;
end;
var
t1, t2: T;
begin
t1 := T.Create(false);
t2 := T.Create(false);
t1.WaitFor;
t2.WaitFor;
WriteLn(s);
ReadLn;
end.
Gibt das Konzept von Message Queues auch im POSIX standard, gibt soweit ich weiß nur keine einheitliche (fpc) implementierung, da sich Windows und Posix (obwohl das konzept gleich ist) doch sehr unterscheiden.mschnell hat geschrieben:Die Message Sachen sind ein "Relikt" aus Windows.
Da fpc aber auf vielen Betriebssystemen läuft, braucht man es nicht. FPC enthält entsprechende "allgemeine" Funktionalitäten im "Sprachumfang".
"Message", "Procedure message", etc verwendet 1:1 die Windows API, wenn das Programm auf Windows läuft und in der Library realisierte Workalikes, wenn das Programm auf einem anderen Betriebbssystem läuft.
Deshalb würde ich Messsage ertc nur verwenden , wenn ich weiß dass das Programm auf Windows laufen wird und spezielle Windows Funktionalität genutzt werden soll.
-Michael
Was man auch benutzen kann ist der IPC client, der ist Thread Safe, und wenn du willst kannst du damit deine Threads sogar in verschiedene Prozesse auslagern. Damit kannst du tatsächlich ne ganze menge Probleme vermeiden, weil du dann keine sorgen mehr um Synchronize, Critical Sections, Deadlocks, etc machen musst. Dafür hast du halt einen recht eingeschränkten kommunikationsweg (nur einen Stream)
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
Das finde ich aber enttäuschend !
Dass das Reference Counting Pobleme machen könnte hatte ich in Erwägung gezogen. Das geht bei einem statisch angelegn String (der ja immer im Fokus ist) aber doch wohl nie auf Null. (Oder doch durch mangelnde Threadfestigkeit ???)
Aber "normale" String Aktivitäten ?!?!?!?!? Die Ergebnisse können bei konkurrierendem Zugriff fragwürdig sein aber Seg-Faults dürften nicht auftreten.
- Ist das dokumentiert ?
- Ist das bei Delphi auch so ?
-Michael
Dass das Reference Counting Pobleme machen könnte hatte ich in Erwägung gezogen. Das geht bei einem statisch angelegn String (der ja immer im Fokus ist) aber doch wohl nie auf Null. (Oder doch durch mangelnde Threadfestigkeit ???)
Aber "normale" String Aktivitäten ?!?!?!?!? Die Ergebnisse können bei konkurrierendem Zugriff fragwürdig sein aber Seg-Faults dürften nicht auftreten.
- Ist das dokumentiert ?
- Ist das bei Delphi auch so ?
-Michael
-
- Lazarusforum e. V.
- Beiträge: 3177
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Multitasking die 1.: CriticalSection
Konstante Strings werden nicht referenzgezählt und haben eine konstante (negative?) RefCount.mschnell hat geschrieben:Das geht bei einem statisch angelegn String aber doch wohl nie auf Null.
Es geht immer um die Fälle des Dereferenzierens. D.h. reine Leseoperationen sind unkritisch.mschnell hat geschrieben:Aber "normale" String Aktivitäten ?!?!?!?!? Die Ergebnisse können bei konkurrierendem Zugriff fragwürdig sein aber Seg-Faults dürften nicht auftreten.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
Meist reicht aber in Richtung Mainthread TThread.Queue und TThread.Synchronize und in Richtung Thread TEvent oder TCriticalSection zur Synchronisation.Warf hat geschrieben:Was man auch benutzen kann ist der IPC client,
-Michael
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Multitasking die 1.: CriticalSection
Nur wenn niemand schreibt, also praktisch String Konstanten sind sicher. Sobald es einen schreibenden Zugriff gibt, kann auch jeder Lesende Zugriff knallenSocke hat geschrieben:Es geht immer um die Fälle des Dereferenzierens. D.h. reine Leseoperationen sind unkritisch.
Code: Alles auswählen
program Project1;
{$mode objfpc}{$H+}
uses classes;
var s: String;
var sum: Integer;
type
TWriteThread = class(TThread)
protected
procedure Execute; override;
end;
TReadThread = class(TThread)
protected
procedure Execute; override;
end;
procedure TReadThread.Execute;
var
j, k: Integer;
str: String;
begin
for j:=0 to 1000000 do
begin
str := s;
for k:=1 to length(str) do
sum := sum + ord(str[k]);
end;
end;
procedure TWriteThread.Execute;
var
i: Integer;
begin
for i:=0 to 1000000 do
begin
if length(s) > 100 then s := '';
s := s + 'a';
end;
end;
var
t1: TWriteThread;
t2: TReadThread;
begin
t1 := TWriteThread.Create(false);
t2 := TReadThread.Create(false);
t1.WaitFor;
t2.WaitFor;
WriteLn(s);
ReadLn;
end.
Doch das geht auf null. Die Operation s := s + 'a'; kann man schreiben als s2 := s + 'a'; s := s2; und dabei wird der alte string überschrieben und damit geht die Referenzzahl auf 0.mschnell hat geschrieben:Das finde ich aber enttäuschend !
Dass das Reference Counting Pobleme machen könnte hatte ich in Erwägung gezogen. Das geht bei einem statisch angelegn String (der ja immer im Fokus ist) aber doch wohl nie auf Null. (Oder doch durch mangelnde Threadfestigkeit ???)
Aber "normale" String Aktivitäten ?!?!?!?!? Die Ergebnisse können bei konkurrierendem Zugriff fragwürdig sein aber Seg-Faults dürften nicht auftreten.
- Ist das dokumentiert ?
- Ist das bei Delphi auch so ?
-Michael
Dokumentiert ist das glaube ich nicht (direkt). Soweit ich weiß ist die allgemeine Annahme das nix thread safe ist, und dazu gehören auch Strings. Ist natürlich verdammt doof da Referenzzählung selbst nicht so trivial ist, und man halt schon recht gut wissen muss was da abgeht, damit man nicht in diese probleme rennt (wie gesagt, selbst lesender zugriff kann zu problemen führen).
Wie der Stand in Delphi ist kann ich nicht sagen, da Delphi meinen Lizensschlüssel anscheinend nicht mehr akzeptieren will
Ich bin auch etwas enttäuscht, denn strings (oder auch arrays) sollten mMn. einfach funktionieren, und die Referenzzählung könnte schon Thread Sicher sein. Was Threading angeht ist der FPC leider ein gutes Stück hinter anderen Programmiersprachen. Java hat z.B. synchronized Methoden (die dann einfach das Objekt zu dem die Methode locken solang sie ausgeführt wird) und selbst C++ hat Thread Sichere standardobjekte. Z.B. shared_ptr ist die C++ implementierung von Referenzzählung, und die ist thread sicher gemacht.
-
- Lazarusforum e. V.
- Beiträge: 3177
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Multitasking die 1.: CriticalSection
In Delphi ist der Stand wohl der selbe: https://stackoverflow.com/questions/263 ... nvironment
In dem dort verlinkten Beitrag (https://stackoverflow.com/questions/197 ... e-property) ist auch ein FPC-fähiges Generic zum sicheren Zugriff auf Variablen enthalten (TThreadsafe).
In dem dort verlinkten Beitrag (https://stackoverflow.com/questions/197 ... e-property) ist auch ein FPC-fähiges Generic zum sicheren Zugriff auf Variablen enthalten (TThreadsafe).
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Multitasking die 1.: CriticalSection
Scheint wohl ein generell schwieriges Problem zu sein. In C# und vielen anderen Sprachen sind Strings "reaonly": wenn man einen String verändern will, muss man immer einen neuen machen.
-Michael
-Michael