複数のスレッドからファイルにログを記録しているときに、競合状態のように見えるものがあります。
1) アプリケーションの複数のスレッドで共有されるカスタム ロガー クラス (ConfigurableTraceLogger) があります。メインコア関数をすべて呼び出すラッパー関数がたくさんあります
protected void TraceData(String category, TraceEventType type, EventId id, string prefix, string format)
{
foreach (TraceListener item in _listeners)
{
IConfigurableTraceListener cl = item as IConfigurableTraceListener;
if (cl != null && cl.Category == category.ToLower())
{
if (DisplayMethodName)
item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format);
else
item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, format);
item.Flush();
}
}
}
ご覧のとおり、私のクラスは、TraceListner から派生したさまざまなクラスをコレクション _listeners に格納するだけです。基本的に、コンソールとテキスト ファイル リスナーのみがあります。TraceData の機能 カテゴリ名 (つまり、ログの開始) を取得し、適切なリスナーを見つけます。すべてのリスナーは構成ファイル名で定義されます
これで、コレクションにカスタム リスナーも追加されました
public class ConfigurableTextWriterTraceListener : TextWriterTraceListener, IConfigurableTraceListener
そのカスタム クラスは、1 つのプロパティを除いて何もオーバーライドしません。
protected override string[] GetSupportedAttributes()
{
return new string[] { "category" };
}
5 ~ 10 分後にアプリケーションを開始すると、通話で例外が発生します
item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format);
例外は言っています:
「メモリのコピー中に I/O 競合状態の可能性が検出されました。I/O パッケージはデフォルトではスレッド セーフではありません。マルチスレッド アプリケーションでは、TextReader によって返されるスレッド セーフ ラッパーなど、スレッド セーフな方法でストリームにアクセスする必要があります。または TextWriter の Synchronized メソッド。これは、StreamWriter や StreamReader などのクラスにも適用されます。」
その後、同じ呼び出しで2番目の例外を何度も取得し続けます
item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format);
例外
カウントを 0 未満にすることはできません。パラメータ名: count スタック トレース: " at System.String.CopyTo(Int32 sourceIndex, Char[] destination, Int32 destinationIndex, Int32 count)\r\n at System.IO.StreamWriter.Write(String value)\r\n at System.IO.StreamWriter.Write(String value) System.Diagnostics.TextWriterTraceListener.Write(String message)\r\n System.Diagnostics.TraceListener.WriteHeader(String source, TraceEventType eventType, Int32 id)\r\n at System.Diagnostics.TraceListener.TraceData(TraceEventCache eventCache, String) source, TraceEventType eventType, Int32 id, Object data)\r\n at Jfc.Configuration.ConfigurableTraceLogger.TraceData(String category, TraceEventType type, EventId id, String prefix, String format, Object[] args)"
私のクラスはTraceDataへの呼び出しと同様にスレッドセーフではないようです。しかし ConfigurableTextWriterTraceListener は結局スレッドセーフと言われています。ただし、実行時に TextWriterTraceListener 派生クラスの IsThreadSafe プロパティをチェックしたところ、false でした。問題がどこにあるのかを理解しようとしています。