![]() |
Reicht Syncronize oder besser Syncronize + CriticalSection ?
Hi Leute,
ich habe einen Indy TCP Server, der ja jede Connection in einem Thread verwaltet. Jetzt lese ich die Daten vom Client und möchte diese in eine Textdatei schreiben. Reicht es das schreiben durch den Aufruf mit Syncronize zu schützen ? Oder das ganze ohne syncronize dafür mit CriticalSection ? Oder beides zusammen ? |
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
Entweder ein von beiden. Beides zusammen ist Quatsch.
|
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
@Luckie:
Was würdest Du machen ? Also der Server erhält ähnlich wie bei einem Chat in kurzen Abständen viele Nachrichten und hat meistens 3-5 Connections simultan. Jetzt will ich halt alles mit loggen und in ne Datei schreiben und als Schutzmechanismus halt etwas Verwenden das am wenigsten Ressoucen verbraucht und am schnellsten ist. Ich tendiere zur CritialSection, weil dann wirklich nur das Schreiben schützen muss, bei Syncronize wird das ganze ja dann aus dem Main-Thread aufgerufen. Sollte also langsamer sein, sehe ich das richtig ? |
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
Kann ich nicht beurteilen, was langsamer ist. Und ob CS oder Synchronize ist geschmackssache.
|
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
Öffne die Datei im Hauptthread
Starte den TCP-Server Vor jedem Zugriff dann Lock.Acquire und danach wieder freigeben. Ist schnellste und beste Methode, da dein Hauptthread nicht belastet wird. Und wenn dieser mal ausgelastet sein sollte funktioniert das Schreiben dennoch. |
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
Critical Section in diesem Fall. Und die Logs dann direkt in die Datei via Append-Modus schreiben. Das ist am schnellsten.
Vermutung: CS ist nicht einmal nötig, da HDD Zugriffe eh synchronisiert sind :zwinker: ...:cat:... |
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
Danke schön, an alle fähigen Gehirne hier :dp:
|
Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
Hi DPler,
Ich habe ein ähnliches Problem. Ich habe eine Log-Klasse welche auch threadsicher FTP aktionen loggen soll. Die Klasse wird aber auch in diversen anderen Programmen benutzt. Das scheint auch ganz gut zu funktionieren aber manchmal bekomme ich AVs und ich weiß nicht genau ob es nun an der Klasse liegt? Ich habe den verdacht das es evtl. Probleme mit Synchronize und Dateizugriffen gibt? Oder ist das TIdSync, von dem TLog abgeleitet ist, nicht die optimale Wahl? Das der Logeintrag auch an das Memo des Protokoll-Forms angehängt wird sollte doch durch Synchronize kein Problem sein, oder? Ein Logeintrag wird über die Klassenproceduren TLog.Add() hinzugefügt. Bin für generelle oder konkrete Hinweise dankbar. Gottes Segen Nun etwas Source:
Delphi-Quellcode:
type
TDaPrtData = record Typ: TDaPrtMsgType; Msg: String; Cls: ShortString; Code: Integer; SQL: String; Details: String; DoId: Integer; ConfigId: Integer; end; //This is based on the example found in the indy newsgroup TLog = class(TIdSync) protected FPrtData: TDaPrtData; procedure DoSynchronize; override; constructor Create(const APrtData: TDaPrtData); public class procedure Add(const APrtData: TDaPrtData); overload; class procedure Add(const AStr: String); overload; end; //---------------------------------------------------// //------------------------ TLog ---------------------// constructor TLog.Create(const APrtData: TDaPrtData); begin FPrtData := APrtData; inherited Create; end; procedure TLog.DoSynchronize; var lFileStream: TFileStream; lMode: Word; lString: String; procedure TruncateStream; var Buffer: TMemoryStream; c, n1, n2, Len: Int64; begin // QueryPerformanceFrequency(c); // QueryPerformanceCounter(n1); Buffer := TMemoryStream.Create; try Buffer.Size := konPrtLowFileSize; lFileStream.Position := lFileStream.Position - konPrtLowFileSize; Len := Buffer.CopyFrom(lFileStream, konPrtLowFileSize); Buffer.Position := 0; lFileStream.Position := 0; //TODO 1: Alternative. Works but sure slow?? lFileStream.Size := 0; lFileStream.Size := konPrtLowFileSize; lFileStream.Position := 0; lFileStream.CopyFrom(Buffer, Len); QueryPerformanceCounter(n2); OutputDebugString(PChar(FloatToStr(n2-n1/c, formatSet))); // TLog.Add(FloatToStr(n2-n1/c, formatSet));//geht nicht - AV!?!¿!? finally Buffer.Free; end; end; procedure LogToScreen; begin try frmProt.memLog.Lines.BeginUpdate; if frmProt.memLog.Lines.Count > frmProt.PrtOptions.PrtSize then begin while frmProt.memLog.Lines.Count > frmProt.PrtOptions.PrtSize-50 do//Cut off 50 Lines frmProt.memLog.Lines.Delete(0); frmProt.memLog.Lines.Add('$$$'+konPrtColDel+DateTimeToStr(Now, formatSet)+'LOG TRUNCATE'+konPrtLineDel); end; frmProt.memLog.Lines.Add(lString); // if True{Optionen_Form.miscAutoScrollLog }then begin frmProt.memLog.Perform(EM_LINESCROLL, 0, frmProt.memLog.Lines.Count); // end; frmProt.memLog.Lines.EndUpdate; except frmProt.PrtOptions.AbledPrtModes := frmProt.PrtOptions.AbledPrtModes - [pmScreen]; end; end;//procedure LogToScreen procedure LogToFile; begin try if FileExists(frmProt.PrtOptions.PrtFileName) then lMode := fmOpenReadWrite or fmShareDenyWrite else lMode := fmCreate; lFileStream := TFileStream.Create(frmProt.PrtOptions.PrtFileName, lMode); try if lMode <> fmCreate then lFileStream.Seek(0, soFromEnd); lFileStream.Write(LString[1], Length(lString)); lFileStream.Write(sLineBreak, Length(sLineBreak)); // <-- sLineBreak is defined by VCL if lFileStream.Size > konPrtHighFileSize then begin TruncateStream; end; finally lFileStream.Free; end; except frmProt.PrtOptions.AbledPrtModes := frmProt.PrtOptions.AbledPrtModes - [pmFile]; end end;//procedure LogToFile begin lString := ''; case FPrtData.Typ of pmtInformation: lString := '###' + konPrtColDel; pmtConfirmation: lString := '???' + konPrtColDel; pmtWarning: lString := 'x!x' + konPrtColDel; pmtError: lString := 'XXX' + konPrtColDel; end; //Using a formatSetting var it is thread save. lString := lString + DateTimeToStr(Now, formatSet) + konPrtColDel + FPrtData.Msg + konPrtColDel + FPrtData.Cls + konPrtColDel + FPrtData.SQL + konPrtColDel + FPrtData.Details + konPrtColDel + IntToStr(FPrtData.DoId) + konPrtColDel + IntToStr(FPrtData.ConfigId) + konPrtLineDel;//2006_01_29 We need a Line-Delimiter cause of multiline prt entries! case frmProt.PrtOptions.PrtUsage of cbChecked: begin if pmScreen in frmProt.PrtOptions.AbledPrtModes then LogToScreen; if pmFile in frmProt.PrtOptions.AbledPrtModes then LogToFile; end; cbGrayed: begin if pmScreen in frmProt.PrtOptions.AbledPrtModes then LogToScreen; end; cbUnchecked:;//nothing end;//case cbUseProt.State end; class procedure TLog.Add(const APrtData: TDaPrtData); begin with TLog.Create(APrtData) do try Synchronize; finally Free; end; end; class procedure TLog.Add(const AStr: String); var LPrtData: TDaPrtData; begin FillChar(LPrtData, SizeOf(LPrtData), #0); LPrtData.Msg := AStr; with TLog.Create(LPrtData) do try Synchronize; finally Free; end; end; //------------------------ TLog ---------------------// //---------------------------------------------------// |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:59 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