The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 4,262 other subscribers

Delphi/Turbo Pascal: AppendWithRetry for text files to retry Append

Posted by jpluimers on 2014/03/10

Every once in a while you have multiple threads or processes wanting to write a short message to the same log file. Append then will give you an I/O error 32 (ERROR_SHARING_VIOLATION), but the below small routine will sleep a bit while retrying a couple of times.

It uses these Delphi aspects around the $I or $IOCHECKS compiler directive:

  • in $I+ mode, you get exceptions when certain “classic” Pascal style I/O operations fail.
  • in $I- mode, you access the IOResult to obtain the results of those I/O operations
  • IOResult gets the result of the last failed operation (if any) or zero if none failed
  • IOResult clears the underlying storage to zero
  • $IFOPT checks for a certain state of a compiler flag
  • You can store the state of $OPT in a temporary conditional define

Note there are a few tables of codes you can get back through IOResult as basically you can get many GetLastError results in IOResult as well:

I wish Embarcadero had done things like this to prevent Delphi IDE startup messages like these:

[RAD Studio]
The imported project file could not be loaded. The process cannot access the file ‘C:\Users\Developer\AppData\Roaming\Embarcadero\BDS\10.0\environment.proj’ because it is being used by another process. C:\Users\Developer\AppData\Roaming\Embarcadero\BDS\10.0\environment.proj.
[OK]

Anyway, here is the code:


//1 do not use 0=aSleepMillisecondsBetweenRetries as Sleep doesn't work predictably then: http://blogs.msdn.com/b/oldnewthing/archive/2005/10/04/476847.aspx
function AppendWithRetry(const aTextFile: TextFile; const aRetryCount: Integer = 10; const aSleepMillisecondsBetweenRetries: Integer = 1): Boolean;
var
lCount: Integer;
lIOResult: Integer;
begin
Result := False;
{$IFOPT I+}
{$DEFINE AppendWithRetry_IPlus}
{$I-}
{$ENDIF I+}
lIOResult := 0;
lCount := aRetryCount;
while lCount > 0 do
begin
Append(aTextFile);
lIOResult := IOResult;
if lIOResult = 0 then
begin
lCount := -1; // no more tries needed
Result := True;
end
else
begin
Sleep(aSleepMillisecondsBetweenRetries);
Dec(lCount);
end;
end;
{$IFDEF AppendWithRetry_IPlus}
{$I+}
if lCount = 0 then
begin // retry once more to see if we can still force a run-time-error
Append(aTextFile); // retry once more
Result := True; // when there was no I/O error, otherwise an exception gets thrown.
end;
{$ENDIF AppendWithRetry_IPlus}
end;

–jeroen

via:

2 Responses to “Delphi/Turbo Pascal: AppendWithRetry for text files to retry Append”

  1. uligerhardt said

    I’m surprised that you haven’t been chastised yet for publicly mentioning old skool IO. :-)

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.