angeregt durch diesen Beitrag:
will ich ein bestehendes Projekt umbauen und bin nach verschiedenen Versuchen immer noch nicht schlauer:mschnell hat geschrieben: - Der GUI Thread darf natürlich nicht warten, sondern muss ein Callback-Event ausführen
- Andere Threads dürfen auf die Events warten.
"Message" an den GUI-Thread kannst Du mit QueueAsyncCall schicken.
Ein Worker-Thread kann mit TEvent.Waitfor auf eine "Message" warten und sie dann bearbeiten wenn ein anderer Thread das Event auslöst.l
Ich habe ein Standalone-Programm, was lange Zeit eigenständig läuft. Zum mitloggen von Fehlern oder falls ich mal wissen, will, was es gerade macht, habe ich ein "Status-Programm" laufen (ähnlich WriteLn oder DebugLn). Es soll threadsicher sein und alle Ereignisse chronologisch schreiben.
Z.Zt. mache ich folgendes (alle Threads inkl. Mainthread greifen auf die Klasse TStatus mit Methode StatLn zu):
Code: Alles auswählen
procedure TStatus.StatLn(const aMethName, aStr: String); //Sendet einen Status
begin
EnterCriticalsection(StatusThread.ACriticalSection);
StatusThread.AktText:='['+IntToStr(FLastView)+']['+aMethName+'] '+aStr;
LeaveCriticalsection(StatusThread.ACriticalSection);
RtlEventSetEvent(StatusThread.StartWrite);
RtlEventWaitFor(StatusThread.EndWrite);
end;
Code: Alles auswählen
procedure TStatusThread.Schreib;
var
s: String;
begin
EnterCriticalsection(ACriticalSection);
s:=AktText;
LeaveCriticalsection(ACriticalSection);
RtlEventSetEvent(EndWrite);
... //hier wird mit SimpleIPC der Text an ein externes Log-Programm übergeben
end;
procedure TStatusThread.Execute;
begin
while not Terminated do begin
RtlEventWaitFor(StartWrite);
Schreib;
end;
end;
Mit Criticalsection, ohne ein Waitfor läuft das Programm in etwa 4 mal so schnell, dafür werden nur ca. 10% aller Meldungen mitgeschrieben und diese nicht chronologisch. Ich habe auch überlegt eine "SammelListe" der Meldungen zu machen. Das führt mMn aber zu höheren String-Kopierungen, die dann ebenfalls Zeit fressen.
Wie könnte ein sauberer Aufbau des Programms aussehen?