Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Reicht Syncronize oder besser Syncronize + CriticalSection ? (https://www.delphipraxis.net/27512-reicht-syncronize-oder-besser-syncronize-criticalsection.html)

DataCool 11. Aug 2004 13:21


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 ?

Luckie 11. Aug 2004 13:31

Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
 
Entweder ein von beiden. Beides zusammen ist Quatsch.

DataCool 11. Aug 2004 13:42

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 ?

Luckie 11. Aug 2004 13:45

Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
 
Kann ich nicht beurteilen, was langsamer ist. Und ob CS oder Synchronize ist geschmackssache.

Vjay 11. Aug 2004 13:46

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.

sakura 11. Aug 2004 13:47

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:...

DataCool 11. Aug 2004 13:49

Re: Reicht Syncronize oder besser Syncronize + CriticalSecti
 
Danke schön, an alle fähigen Gehirne hier :dp:

Meta777 27. Mär 2006 22:31

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 20:13 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