线程安全日志类实现
以下是实现相当简单的线程安全日志记录类的正确方法吗?
我知道我从未明确关闭 TextWriter
,这会是一个问题吗?
当我最初使用 TextWriter.Synchronized 方法时,它似乎不起作用,直到我在静态构造函数中初始化它并将其设置为只读,如下所示:
public static class Logger
{
static readonly TextWriter tw;
static Logger()
{
tw = TextWriter.Synchronized(File.AppendText(SPath() + "\\Log.txt"));
}
public static string SPath()
{
return ConfigManager.GetAppSetting("logPath");
}
public static void Write(string logMessage)
{
try
{
Log(logMessage, tw);
}
catch (IOException e)
{
tw.Close();
}
}
public static void Log(string logMessage, TextWriter w)
{
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
}
}
Would the following be the correct way to implement a fairly straightforward thread-safe logging class?
I know that I never explicitly close the TextWriter
, would that be a problem?
When I initially used the TextWriter.Synchronized
method, it did not seem to work until I initialized it in a static constructor and made it readonly like so:
public static class Logger
{
static readonly TextWriter tw;
static Logger()
{
tw = TextWriter.Synchronized(File.AppendText(SPath() + "\\Log.txt"));
}
public static string SPath()
{
return ConfigManager.GetAppSetting("logPath");
}
public static void Write(string logMessage)
{
try
{
Log(logMessage, tw);
}
catch (IOException e)
{
tw.Close();
}
}
public static void Log(string logMessage, TextWriter w)
{
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我将在这里采取与其他答案完全不同的方法,并假设您实际上想学习如何编写更好的线程感知代码,并且不寻求我们的第 3 方建议(即使您实际上可能最终使用一个。)
正如其他人所说,您正在创建一个线程安全的
TextWriter
这意味着对 WriteLine 的调用是线程安全的,这并不意味着对WriteLine
的大量调用> 将作为原子操作执行。我的意思是不能保证四个 WriteLine 调用会按顺序发生。您可能有一个线程安全的TextWriter
,但没有线程安全的Logger.Log
方法;)为什么?因为在这四个调用期间的任何时候,另一个线程都可能决定也调用Log
。这意味着您的WriteLine
调用将不同步。解决这个问题的方法是使用像这样的lock
语句:所以,现在你有一个线程安全的
TextWriter
和一个线程安全的Logger
>。有道理吗?
I'm going to take a completely different approach here than the other answers and assume you actually want to learn how to write better thread-aware code, and are not looking for 3rd party suggestions from us (even though you may actually end up using one.)
As others have said, you are creating a thread safe
TextWriter
which means calls to WriteLine are thread-safe, that doesn't mean that a bunch of calls toWriteLine
are going to be performed as an atomic operation. By that I mean there is no guarantee that the four WriteLine calls are going to happen in sequence. You may have a thread-safeTextWriter
, but you don't have a thread-safeLogger.Log
method ;) Why? Because at any point during those four calls, another thread might decide to callLog
also. This means yourWriteLine
calls will be out of sync. The way to fix this is by using alock
statement like so:So, now you have a thread-safe
TextWriter
AND a thread-safeLogger
.Make sense?
今天有人在讨论一些日志记录问题时向我指出了这篇文章。我们在这里已经有了很好的答案,但我添加我的答案只是为了展示 Logger 类的更简单版本,它以完全线程安全的方式执行完全相同的操作.
这里需要注意的一件主要事情是,线程安全不需要
TextWriter.Synchronized
,因为我们是在适当的锁
内写入文件。注意:这已经在 x0n 答案的评论部分讨论过。
要记录某些内容,只需调用 as
它就会生成如下所示的日志条目
Someone pointed me to this post while discussing some logging issues today. We already have pretty good answers here, but I'm adding my answer just to show a simpler version of the
Logger
class which does the exact same thing, in completelyThreadsafe
way.One main thing to notice here is, no
TextWriter.Synchronized
is required for thread safety, as we are writing the file within a properlock
.Note: This has already been discussed in the comments section of x0n's answer.
To log something, simply call as
And it will make a log entry like this
调用 TextWriter.Synchronized 将保护
的单个实例TextWriter
,它不会同步您的写入,因此一个“Log”调用会保留在文件内。如果您从多个线程调用
Write
(或使用内部TextWriter
实例的Log
),则各个WriteLine
调用可能会交织在一起,使您的日期和时间戳无法使用。我个人会使用已经存在的第三方日志记录解决方案。如果这不是一个选项,那么自己同步它(即使使用简单的锁)可能比使用框架的
TextWriter.Synchronized
包装器更有用。While calling TextWriter.Synchronized will protect that single instance of
TextWriter
, it will not synchronize your writes so that one "Log" call stays together inside of the file.If you call
Write
(orLog
using the internalTextWriter
instance) from multiple threads, the individualWriteLine
calls may be interwoven, making your date and time stamps unusable.I would personally use a third party logging solution that already exists for this. If that is not an option, synchronizing this yourself (even with a simple lock) will likely be more useful than using the framework's
TextWriter.Synchronized
wrapper.您应该研究这个类(.NET 2.0 的一部分),无需“创建”您自己的记录器。使您能够登录到文本文件、事件视图等。
http ://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx
您的“Log”方法可能看起来像这样(假设有一个名为'traceSource'):
支持此功能的是一个配置部分,它命名 TraceSource 并具有一些配置设置。假设当您在记录器中构造 TraceSource 时,您将使用配置中指定的跟踪源之一实例化它。
另外,不要让你的记录器静态。相反,使用 Enterprise Library 5.0 Unity 进行依赖注入/IOC。
希望这有帮助!
You should look into this class (part of .NET 2.0), no need to "create" your own logger. enables you to log to a text file, event view, etc.
http://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx
Your "Log" method can look something like this (assuming there is an intermal member variable called 'traceSource'):
Supporting this is a config section that names the TraceSource and has some Config settings. It is assumed that when you construct a TraceSource in your logger you are instantiating it with one of the trace sources named in the config.
Also, don't make your logger static. Instead, use Enterprise Library 5.0 Unity for Dependency Injection / IOC.
Hope this helps!
如果您正在寻找一种简单的方法来检测代码,.NET 中已经存在该工具:
http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx
此外,第三方工具将为您提供强大的日志记录解决方案;示例包括 log4net、nLog,以及企业库。
我真的建议不要在这方面重新发明轮子:)
If you're looking for a simple method of instrumenting your code, the facility already exists within .NET:
http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx
Additionally, third party tools will give you robust solutions for logging; examples include log4net, nLog, and the Enterprise Library.
I really recommend not reinventing the wheel on this :)