应用说明:
我有一个应用程序允许用户通过线程运行多个并发查询(一次最多 100 个)。
我有一个用于记录错误的类。如果应用程序中发生错误,我会创建该类的一个实例并调用一个过程将错误写入日志文件。
问题:
我需要使错误记录代码线程安全。我注意到如果很多线程同时运行并产生相同的错误(例如无法连接到数据库),我会收到 i/o 错误 32(由于应用程序试图写入文件已经开放)。
作为一个快速而肮脏的修复,我已将写入文件的代码放在 try... 除了块内的重复循环中。如果出现异常(例如,该文件已被该类的另一个实例打开,由另一个线程启动),则它将标志设置为“false”。循环继续执行,直到标志为“真”(即没有错误写入文件),如下:
procedure TErrorLogging.logError(error: string);
var
f: textfile;
ok: boolean;
begin
repeat
ok := true;
try
assignfile(f, fLogFilename);
if fileExists(fLogFilename) then append(f) else rewrite(f);
writeln(f, error);
closefile(f);
except
ok := false;
end;
until ok;
end;
我知道保护代码块的正确方法是使用关键部分,但我不确定如何实现它,因为有许多不同的线程使用日志记录类,并且每个实例线程有自己的日志类实例,用于写入文件(因此它们不都只是与同一块代码同步)。
我可以看到的选项:
- 使用上面的代码。保留此代码是否有任何问题?这是一个快速而肮脏的修复,但它有效。
- 使用全局 TcriticalSection(如何?)。
- 在某处使用单个过程来创建日志记录类的实例,线程将与之同步(我想这会破坏拥有日志记录类的对象)。