c#静态对象引用

时间:2015-03-02 10:50:29

标签: c# .net multithreading static log4net

我有一个类似的课程

public class FileLogger
{
   public FileLogger(string typeOfLog)
   {
    //implementation
   }

   public void LogError(string err)
   {
    //implementation
   }

   public void LogMessage(string err)
   {
    //implementation
   }
}

由于这是应用程序将其输出记录到文件的日志记录类,因此可以预期它将成为静态类。但是你可以看到它不是。然而,它在这样的应用程序中使用:

public class BugetApplication 
{
     private static FileLogger logger;

    //constructor
    public BugetApplicationClass()
    {
       logger = new FileLogger("some-constructor-parameter"); 
    }

    //a method that uses the FileLogger class for logging
    public string Classify()
    {
        try
        {
           //start multiple threads for classification
           Classification clsf = new Classification();
           clsf.handleEvent += clsf_handleEvent;
           clsf.Classify(); 
        }
        catch (Exception exp)
        {
           logger.LogError(exp.Message);
        }
    }

    private static void clsf_handleEvent(string errString)
    {
       if(errString.Contains("error"))
       {
          logger.LogError(errString);
       }
    } 

}

BugetApplication类的classify方法启动了多个线程。该类中的任何错误都会触发在BugetApplication类的clsf_handleEvent方法中处理的事件。因此,多个线程可以各自触发自己的事件。将实例变量创建为BugetApplication类中的静态变量会在此处产生任何影响,还是将其保持为非静态具有相同的效果?我不希望任何一个线程覆盖另一个线程的错误消息。

修改 只是为了清除问题,只创建一次的BugetApplication类有一个静态变量'静态FileLogger记录器; '它在构造函数中创建一个实例,将一些值传递给FileLogger类的构造函数。在BugetApplication类中,有一个方法可以调用Classification类的分类方法。 Classify方法启动各种线程,并且在任何错误上触发在BugetApplication类中处理的事件,因此clsf_handleEvent方法可以对其进行多次调用。

2 个答案:

答案 0 :(得分:2)

为什么你认为它会覆盖另一个线程的错误信息?记录器应该只附加消息,因此不应该覆盖任何内容(取决于您如何处理日志记录)。但是存在一个潜在的问题 - 根据您的日志记录功能,您可能会阻止访问该文件。由于该方法适用于外部文件,因此您应该在函数中使用lock

如果类是静态的并不重要,问题是并发访问外部资源,需要同步多个线程以成为线程安全的。

lock documentation on msdn

答案 1 :(得分:1)

这实际上取决于记录器的实际实现。 静态类现在不受欢迎,因为它们使单元测试更加困难。传统上以静态或单一(记录器,电子邮件等)实现的许多设施现在提供单元测试/ IoC友好的替代方案(例如工厂和接口或虚拟类)。

这些工具的设计通常是客户端应用程序用于交互的前端类,以及负责同步和实际日志记录(或电子邮件或其他)的异步后端。

关键是前端是否是多线程的。

如果他们不是;你应该为每个线程创建一个新的。在这种情况下,记录器可能必须是使用它的方法的局部变量或参数。

但是,它们通常是多线程和可重入的,因为他们只是将日志消息传递给后端并且没有自己的状态。在这种情况下,它们可以保存为静态变量或应用程序范围的单例,但最好将它们作为单例在IoC容器中实例化,并使用它们将它注入类。这样做可以更容易地使用模拟记录器编写单元测试。