Recent

Author Topic: [SOLVED] Cannot catch exception  (Read 2219 times)

tudi_x

  • Hero Member
  • *****
  • Posts: 532
[SOLVED] Cannot catch exception
« on: November 22, 2017, 02:24:26 pm »
hi All,
i am just learning to raise exceptions.
in the attached and below i would like to raise an exception when trying to append to the logger but the logger is still busy (not yet accepting information to log).
i defined an exception type (12 and line 96) and condition to raise it, i see the exception line number in the console when using Heaptrc but i do not see the exception message in the try in main unit in:
Code: Pascal  [Select][+][-]
  1.     try
  2.       l.PToAppend := 'message 4';
  3.     except
  4.       on E: Exception do
  5.       begin
  6.         writeln('exception TMyLogger.DoRun: ' + E.Message);
  7.       end;
  8.     end;
please advise what i am missing.
thank you

Code: Pascal  [Select][+][-]
  1. unit tlogger;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, LCLIntf;
  9.  
  10. type
  11.   TInfos = array of string;
  12.   CannotAppendException = class(Exception);
  13.  
  14.   TQLogger = class(TThread)
  15.   private
  16.     _Infos: TInfos;
  17.     _FName: string;
  18.     _CanAppend: boolean;  //wait to write current
  19.     _ToAppend: string;
  20.  
  21.     procedure ReceiveToApend(AToAppend: string);
  22.  
  23.   protected
  24.     procedure Execute(); override;
  25.  
  26.   public
  27.     constructor Create(AFileName: string); reintroduce;
  28.     destructor Destroy(); override;
  29.     property PCurrentLogFile: string read _FName;
  30.     property PCanAppend: boolean read _CanAppend;
  31.     property PToAppend: string read _ToAppend write ReceiveToApend;
  32.   end;
  33.  
  34.  
  35. implementation
  36.  
  37. constructor TQLogger.Create(AFileName: string);
  38. begin
  39.   _FName := AFileName;
  40.   SetLength(_Infos, 0);
  41.  
  42.   inherited Create(False);
  43. end;
  44.  
  45. procedure TQLogger.Execute();
  46. var
  47.   f: TextFile;
  48.   i: word;
  49.  
  50. begin
  51.   {Create new file}
  52.   AssignFile(f, _FName);
  53.   ReWrite(f);
  54.   CloseFile(f);
  55.  
  56.   _CanAppend := True;
  57.  
  58.   while not Terminated do
  59.   begin
  60.  
  61.     if Length(_Infos) > 0 then
  62.     begin
  63.       try
  64.         _CanAppend := False;
  65.         Append(f);
  66.  
  67.         repeat
  68.           WriteLn(f, _Infos[0]);
  69.  
  70.           for i := 1 to Length(_Infos) - 1 do
  71.           begin
  72.             _Infos[i - 1] := _Infos[i];
  73.           end;
  74.           SetLength(_Infos, Length(_Infos) - 1);     //delete element that was just written
  75.         until Length(_Infos) = 0;
  76.  
  77.         CloseFile(f);
  78.  
  79.         sleep(1000);
  80.         _CanAppend := True;
  81.  
  82.       except
  83.         on E: Exception do
  84.         begin
  85.           writeln('exception: ' + E.Message);
  86.         end;
  87.       end;
  88.     end;
  89.  
  90.     sleep(50);
  91.   end;
  92. end;
  93.  
  94. procedure TQLogger.ReceiveToApend(AToAppend: string);
  95. begin
  96.     if not _CanAppend then
  97.       CannotAppendException.Create('Cannot append: ' + AToAppend);
  98.  
  99.     if Length(trim(AToAppend)) > 0 then
  100.     begin
  101.       SetLength(_Infos, Length(_Infos) + 1);
  102.       _Infos[Length(_Infos) - 1] := FormatDateTime('hh:nn:ss.zzz', Now()) + '|' + AToAppend;
  103.     end;
  104. end;
  105.  
  106. destructor TQLogger.Destroy();
  107. begin
  108.   inherited Destroy;
  109. end;
  110.  
  111. end.
  112.  
« Last Edit: November 22, 2017, 02:57:02 pm by tudi_x »
Lazarus 2.0.2 64b on Debian LXDE 10

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Cannot catch exception
« Reply #1 on: November 22, 2017, 02:51:38 pm »
You need to raise the exception:

Code: Pascal  [Select][+][-]
  1. procedure TQLogger.ReceiveToApend(AToAppend: string);
  2. begin
  3.     if not _CanAppend then
  4.       raise CannotAppendException.Create('Cannot append: ' + AToAppend);
  5.  
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

tudi_x

  • Hero Member
  • *****
  • Posts: 532
Re: Cannot catch exception
« Reply #2 on: November 22, 2017, 02:56:48 pm »
awesome. thank you!
Lazarus 2.0.2 64b on Debian LXDE 10

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Cannot catch exception
« Reply #3 on: November 22, 2017, 03:03:25 pm »
Exceptions are thread specific, you can not raise them in one thread and capture them in an other, even if that "other thread" is the main application thread. Threads must implement their own exception handling or they will crash. in your example though you call ReceiveToApend in the main thread context which should allow you to capture the exception if it is raised during your call.

Then again you do not protect your data access properly for multi threading. It is possible that _canAppend could be true and pass with out raising the exception but become false shortly after. Why don't you use a more "safe" list like tthreadedlist or a tthreadedStringlist? Or at least study one to see the minimum requirements for a thread safe container.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

tudi_x

  • Hero Member
  • *****
  • Posts: 532
Re: [SOLVED] Cannot catch exception
« Reply #4 on: November 22, 2017, 03:46:53 pm »
thank you taazz.
critical section and TThreadList are next on my todo's now.
i did not find good examples of TThreadList but maybe its code would help more.
Lazarus 2.0.2 64b on Debian LXDE 10

 

TinyPortal © 2005-2018