从多线程记录到文件时,我有一些看起来像竞争条件的东西。
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
该自定义类只覆盖一个属性。
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 等类。
之后,我在同一次调用中不断收到第二个异常
item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format);
例外
计数不能小于零。参数名称: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.Diagnostics.TextWriterTraceListener.Write(String message)\r\n 在 System.Diagnostics.TraceListener.WriteHeader(String source, TraceEventType eventType, Int32 id)\r\n 在 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 属性,它是错误的。我试图找出问题出在哪里。