アプリケーションの説明:
ユーザーがスレッドを介して複数の同時クエリを実行できるようにするアプリケーションがあります(一度に最大100)。
エラーのログ記録に使用するクラスがあります。アプリケーションでエラーが発生した場合は、クラスのインスタンスを作成し、プロシージャを呼び出してエラーをログファイルに書き込みます。
質問:
エラーロギングコードスレッドを安全にする必要があります。多くのスレッドが同時に実行され、同じエラーを生成している場合(たとえば、データベースに接続できない場合)、I / Oエラー32が発生していることに気付きました(アプリケーションが次のファイルに書き込もうとしたことが原因です)。すでに開いています)。
迅速で汚い修正として、ファイルに書き込むコードを試してみました...繰り返しループ内のブロックを除きます。例外がある場合(たとえば、ファイルがクラスの別のインスタンスによってすでに開かれている場合、別のスレッドによって開始されている場合)、フラグが「false」に設定されます。次のように、フラグが「true」になるまで(つまり、ファイルへの書き込みエラーが発生しなくなるまで)、ループは実行を続けます。
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を使用します(どのように?)。
- スレッドが同期するロギングクラスのインスタンスを作成する単一のプロシージャをどこかで使用します(これにより、ロギングクラスを持つというオブジェクトが無効になると思います)。