Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 12-03-2008
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
WaitForSingleObject se queda bloqueada

Tengo una pequeña funcion para guardar mensajes de log en un archivo (la misma que publique en la seccion de trucos). La funcion funciona muy bien, y nunca me habia dado problemas hasta ahora

El problema aparece cuando se crean varios threads y desde todos ellos se llama a la funcion. Al principio parece que aguanta bien, ya la he usado en varios programas con threads sin problemas, pero cuando se hace un uso muy intensivo de la misma a veces falla. Cuando falla, la funcion WaitForSingleObject se queda esperando indefinidamente, bloqueando asi el thread que llamo la funcion.

El codigo es el siguiente (abajo pongo un ejemplo en un zip)
Código Delphi [-]
unit ULog;

interface

uses Windows, Sysutils, dialogs;  

procedure log(Archivo, Mensaje: String); overload;
procedure log(Mensaje: String); overload;

implementation

var
  LogFile: String;
  Mutex: THandle;

procedure log(Archivo, Mensaje: String); overload;
var
  F: TextFile;
  SearchRec: TSearchRec;
  Str: String;
begin
  if Mutex <> 0 then
  begin
    // Aqui esta el problema
    WaitForSingleObject(Mutex, INFINITE);
    try
      if FindFirst(Archivo,faAnyFile,SearchRec) = 0 then
      begin
        if SearchRec.Size > (1024*1024) then
        begin
          Str:= IncludeTrailingPathDelimiter(ExtractFilePath(Archivo))
            + 'Historico\';
          ForceDirectories(Str);
          MoveFileEx(PChar(Archivo),PChar(Str + FormatDateTime('yyyymmdd',Now)
            + '.log'), MOVEFILE_REPLACE_EXISTING);
        end;
        FindClose(SearchRec);
      end;
      try
        AssignFile(F, Archivo);
        {$I-}
          Append(F);
        if IOResult <> 0 then
          Rewrite(F);
        {$I+}
        if IOResult = 0 then
        begin
          Writeln(F,Mensaje);
          CloseFile(F);
        end;
      except
        //
      end;
    finally
      // Aqui me aseguro de liberar el mutex
      ReleaseMutex(Mutex);
    end;
  end;
end;

procedure log(Mensaje: String); overload;
begin
  try
    Mensaje:= FormatDateTime('[ddd dd mmm, hh:nn] ', Now) + Mensaje;
    log(LogFile,Mensaje);
  except
    //
  end;
end;

initialization
  LogFile:= ChangeFileExt(ParamStr(0),'.log');
  Mutex:= CreateMutex(nil,TRUE,
    PChar(StringReplace(LogFile,'\','/',[rfReplaceAll])));
finalization
  CloseHandle(Mutex);
end.

Y para probar la funcion utilizo el siguiente codigo:
Código Delphi [-]
program logtest;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  Messages,
  Classes,
  ULog in 'ULog.pas';

type
  TTestThread = class(TThread)
  protected
    procedure Execute; override;
  end;

var
  ThreadCount: Integer;

{ TTestThread }
procedure TTestThread.Execute;
var
  i: Integer;
begin
  InterlockedIncrement(ThreadCount);
  for i:= 0 to 10 do
  begin
    log(Format('[%d] %d',[Handle,i]));
    Sleep(10);
  end;
  InterlockedDecrement(ThreadCount);
end;

var
  j,k: Integer;
begin
  j:= 0;
  ThreadCount:= 0;
  while TRUE do
  begin
    // Si no hay threads lanzo 5
    if ThreadCount = 0 then
    begin
      for k:= 1 to 5 do
      begin
        inc(j);
        Writeln(Format('Creado un nuevo Thread: %d',[j]));
        TTestThread.Create(FALSE).FreeOnTerminate:= TRUE;
      end;
    end else;
      Sleep(10);
  end; 
end.

No se que puede estar fallando, hasta utilizo un bloque "try ... finally" para asegurarme de que se libera el mutex, pero aun asi nada

¿Alguien puede ver lo que se me escapa? El problema se podria solucionar cambiando el parametro INFINITE por un tiempo mas pequeño, pero ademas de que eso seria una chapuza, se perderian mensajes.
Archivos Adjuntos
Tipo de Archivo: zip logtest.zip (4,0 KB, 8 visitas)

Última edición por seoane fecha: 12-03-2008 a las 23:14:46.
Responder Con Cita
  #2  
Antiguo 12-03-2008
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Ya me respondo yo , el problema estaba aquí:
Código Delphi [-]
  Mutex:= CreateMutex(nil,TRUE,
    PChar(StringReplace(LogFile,'\','/',[rfReplaceAll])));

Me estaba apropiando del mutex al crearlo y no lo estaba liberando

Solución:
Código Delphi [-]
Mutex:= CreateMutex(nil,FALSE,
    PChar(StringReplace(LogFile,'\','/',[rfReplaceAll])));

Llevo varios días dándole vueltas y hasta que lo publique no me dí cuenta de ese detalle.
Responder Con Cita
  #3  
Antiguo 12-03-2008
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Probando el programa de ejemplo que has puesto, ¿cuándo se supone que falla? Supongo que cuando se crean cinco hilos (generalmente) y no se continua adelante. ¿Es así? Puesto que si abres varias instancias del programa y, cierras alguna, no siempre, pero, a veces los hilos comienzan a crearse "sin límite", que es lo que se supone que tiene que pasar siempre, si no me equivoco.

Lamento no saber decir Domingo, sólo tenía esas dudas, por un lado, y, por otro, quizás algo extraño, y es que, si en lugar de "INIFINITE", como has dicho, lo cambio por algunos milisegundos, el programa se comporta igual, y, esto me confunde, porque antes dijiste que con eso podría solucionarse, pero, que, era una chapuza. Sea o no una chapuza (que si tú lo dices será así) digo que el programa se comporta igual en mi caso.

Windows XP SP2
Delphi 2007 for Win32

Edito: Ya vi que encontraste la solución. También la probé y funciona bien todo. Pues nada, eres más rápido tú en preguntar y solucionar que yo en tratar de decir esta boca es mía nada más...
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 12-03-2008 a las 23:47:27.
Responder Con Cita
  #4  
Antiguo 12-03-2008
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Pues ya ves dec, un simple TRUE casi me vuelve loco

Lo que quedo claro es que escribir en el foro es toda una catarsis
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
me queda el relojito de arena pmfras Conexión con bases de datos 7 28-09-2006 17:15:59
uso de WaitForSingleObject para hacer un instalador crievep Varios 5 05-04-2006 02:05:35
Lepe no se queda atras vtdeleon Noticias 10 10-11-2005 13:37:02
Bloqueada solo una tabla de varias en pdx purhé Tablas planas 1 26-07-2005 07:43:11


La franja horaria es GMT +2. Ahora son las 03:47:44.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi