Pregunta Implementar el registro seguro de subprocesos


Mi tarea es crear una clase que reúna la actividad del usuario en varias aplicaciones.

Digamos que tengo una clase TLogging y un objeto global llamado Logging.

La actividad del usuario (pantalla abierta, etc ...) se debe recopilar en la memoria (tal vez se debe colocar en una lista (cadena) de TLogging) y guardado en el archivo de registro después de algún intervalo de tiempo (cada 10 minutos), o cuando se cierra la aplicación.

Lo más importante es que el registro debe estar en "modo silencioso", no debe afectar el flujo de trabajo del usuario de ninguna manera: no se cuelga la pantalla, no hay excepciones.

Por favor, dame la dirección para esta tarea.


5
2017-11-15 10:02


origen


Respuestas:


Esta es una pregunta muy amplia que toca varias áreas. Algunos consejos:

  • Al menos considere un marco de registro establecido para esto. Las versiones más nuevas de Delphi vienen con CodeSite. SmartInspect es otra alternativa.

  • Use primitivas de sincronización para hacer su clase segura para subprocesos: TCriticalSection, TMREWSync

  • Asegúrese de comprender los problemas relacionados con el multihilo y la sincronización antes de intentar escribir un marco de trabajo seguro para subprocesos. Un buen comienzo es la guía de Martin Harvey. Multithreading - La forma Delphi.

  • Use un hilo de fondo que vacíe el contenido del registro en el disco en intervalos regulares o si se han almacenado suficientes datos en el búfer.

  • Haga preguntas más específicas aquí en SO si encuentra problemas específicos.


14
2017-11-15 10:20



Usar OmniThreadLibrary y suponiendo que el objeto de registro es un singleton, esto es realmente simple. También limitaría la cantidad máxima de mensajes que esperan escribirse para que la cola interna no pueda usar demasiada memoria.

const
  CMaxMsgCount = 1000;
  CMaxLogTimeout_ms = 10{min}*60{sec/min}*1000{ms/sec};

type
  TLogging = class
  strict private
    FLogMsgCount: IOmniResourceCount;
    FLogQueue: IOmniBlockingCollection;
    FWriter: IOmniTaskControl;
  strict protected
    procedure Logger(const task: IOmniTask);
  public
    constructor Create;
    destructor  Destroy;
    procedure Log(const msg: string);
  end;

var
  Logging: TLogging;

constructor TLogging.Create;
begin
  FLogMsgCount := CreateResourceCount(CMaxMsgCount);
  FLogQueue := TOmniBlockingCollection.Create;
  FWriter := CreateTask(Logger, 'Logger').Run;
end;

destructor TLogging.Destroy;
begin
  FWriter.Terminate;
end;

procedure TLogging.Log(const msg: string);
begin
  FLogQueue.Add(msg);
  FLogMsgCount.Allocate;
end;

procedure TLogging.Logger(const task: IOmniTask);

  procedure Flush;
  var
    logData: TOmniValue;
  begin
    // open file, possibly with retry
    while FLogQueue.TryTake(logData) do begin
      FLogMsgCount.Release;
      // write logData.AsString
    end;
    // close file
  end;

begin
  while DSiWaitForTwoObjects(task.TerminateEvent, FLogMsgCount.Handle, false, CMaxLogTimeout_ms) <> WAIT_OBJECT_0 do
    Flush;
  Flush;
end;

(Descargo de responsabilidad: "Se compila en mi máquina", de lo contrario no probado).


3
2017-11-15 16:10