2

从多线程记录到文件时,我有一些看起来像竞争条件的东西。

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 属性,它是错误的。我试图找出问题出在哪里。

4

1 回答 1

1

这意味着什么 - 您的 TraceListener 不是线程安全的,并且在从多个线程访问时会中断。您需要使您的侦听器线程安全或找到一种方法来确保只有一个线程访问任何特定实例。

使它们成为线程安全的一种方法是使用同步队列并使所有调用将数据项排入队列,而“真正的”traceListener 将它们出列并在单独的线程中写出。

您还必须小心您的侦听器字典 - 更新字典不是线程安全的,但如果您在应用最后一次更新之前从未访问它,您可以保持原样

于 2009-11-09T16:16:49.353 回答