競合状態/は、TextWriterTraceListener
-
19-09-2019 - |
質問
私はからファイルへのログイン中ウィッヒは、競合状態のように私には見える何かを持っています 複数のスレッドます。
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-dervedクラスを格納し _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パッケージは、デフォルトではスレッドセーフではありません。マルチスレッドアプリケーションでは、ストリームは、スレッドとして、スレッドセーフな方法でアクセスする必要があります-safeラッパーはしたTextReaderのかたTextWriterのsynchronizedメソッドによって返された。これはまたのStreamWriterとStreamReaderをのようなクラスに適用されます。 "の
私は同じ呼び出しで倍の2番目の例外の多くを取得しておく。その後、
item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format);
例外
のカウントがゼロより小さくすることはできません。 パラメータ名:数 スタックトレース:「System.String.CopyTo(のInt32 sourceIndex、シャア[]先のInt32 destinationIndex、のInt32カウント)で\ R \ nはSystem.IO.StreamWriter.Write(文字列値)で\ R \ NたSystem.Diagnosticsで。 TextWriterTraceListener.Write(文字列メッセージ)\ R \ nはSystem.Diagnostics.TraceListener.WriteHeader(文字列のソース、TraceEventTypeのeventType、のInt32のID)で\ R \ nはSystem.Diagnostics.TraceListener.TraceData(TraceEventCache eventCache、文字列のソース、TraceEventTypeのeventTypeで、のInt32 ID、オブジェクトデータ)\ R \ N Jfc.Configuration.ConfigurableTraceLogger.TraceDataで(文字列カテゴリ、TraceEventType型でEventIdのID、文字列の接頭文字列形式、オブジェクト[]引数) "
私のクラスは、安全だけでなくTRACEDATAへの呼び出しをスレッドされていないように私には思えます。しかしConfigurableTextWriterTraceListenerは、すべての後に、スレッドセーフであると言われています。しかし、私は、実行時に私は、TextWriterTraceListener派生クラスのでisThreadSafeのpropetyをチェックします そして、それはfalse。私は、問題がどこにあるか把握しようとしています。
解決
これは、言うことを意味します。あなたはリスナーがスレッドセーフか一つだけのスレッドが任意の特定のインスタンスにアクセスすることを確実にする方法を見つけるようにする必要があります。
それらをスレッドセーフにする一つの方法は、同期キューを使用し、「実際の」のTraceListenerがそれらをデキューし、別のスレッドでそれらを書き出しながら、すべての呼び出しがキューにデータ項目をエンキューすることです。
また、リスナーのあなたの辞書と注意する必要があります - 辞書を更新することはスレッドセーフではありませんが、最後の更新が適用される前に、あなたがそれにアクセスすることはありません場合は、
があるとして、あなたはそれを残すことができます