我有一个类似的课程
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方法可以对其进行多次调用。
答案 0 :(得分:2)
为什么你认为它会覆盖另一个线程的错误信息?记录器应该只附加消息,因此不应该覆盖任何内容(取决于您如何处理日志记录)。但是存在一个潜在的问题 - 根据您的日志记录功能,您可能会阻止访问该文件。由于该方法适用于外部文件,因此您应该在函数中使用lock
。
如果类是静态的并不重要,问题是并发访问外部资源,需要同步多个线程以成为线程安全的。
答案 1 :(得分:1)
这实际上取决于记录器的实际实现。 静态类现在不受欢迎,因为它们使单元测试更加困难。传统上以静态或单一(记录器,电子邮件等)实现的许多设施现在提供单元测试/ IoC友好的替代方案(例如工厂和接口或虚拟类)。
这些工具的设计通常是客户端应用程序用于交互的前端类,以及负责同步和实际日志记录(或电子邮件或其他)的异步后端。
关键是前端是否是多线程的。
如果他们不是;你应该为每个线程创建一个新的。在这种情况下,记录器可能必须是使用它的方法的局部变量或参数。
但是,它们通常是多线程和可重入的,因为他们只是将日志消息传递给后端并且没有自己的状态。在这种情况下,它们可以保存为静态变量或应用程序范围的单例,但最好将它们作为单例在IoC容器中实例化,并使用它们将它注入类。这样做可以更容易地使用模拟记录器编写单元测试。