我有两个ASP.NET Web应用程序。一个负责处理一些信息并写入日志文件,另一个应用程序负责读取日志文件并根据用户请求显示信息。
这是我的Writer代码
public static void WriteLog(String PathToLogFile, String Message)
{
Mutex FileLock = new Mutex(false, "LogFileMutex");
try
{
FileLock.WaitOne();
using (StreamWriter sw = File.AppendText(FilePath))
{
sw.WriteLine(Message);
sw.Close();
}
}
catch (Exception ex)
{
LogUtil.WriteToSystemLog(ex);
}
finally
{
FileLock.ReleaseMutex();
}
}
这是我的读者代码:
private String ReadLog(String PathToLogFile)
{
FileStream fs = new FileStream(
PathToLogFile, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
StreamReader Reader = new StreamReader(fs);
return Reader.ReadToEnd();
}
我的问题,上面的代码是否足以阻止在网络环境中锁定environemnt?
编辑1:脏读是可以的。 编辑2:使用新互斥锁创建互斥锁(false,“LogFileMutex”),关闭StreamWriter
答案 0 :(得分:7)
听起来像是在尝试实现基本队列。为什么不使用一个为您提供保证可用性的队列。您可以将消息放入MSMQ,然后实现一个Windows服务,该服务将从队列中读取并将消息推送到DB。如果写入数据库失败,你只需将消息留在队列中(虽然你会想要处理posion消息,所以如果它失败导致数据不好,你就不会陷入无限循环)
这将消除所有锁定问题,并为您的读者提供保证交付......
答案 1 :(得分:1)
你也应该处理你的互斥体,因为它来自WaitHandle,而WaitHandle实现了IDisposable:
using (Mutex FileLock = new Mutex(true, "LogFileMutex"))
{
// ...
}
此外,或许可以考虑一个比“LogFileMutex”更独特的名称(可能是GUID),因为另一个不相关的进程可能会无意中使用相同的名称。
答案 2 :(得分:0)
在基于Web的环境中执行此操作,您将遇到很多文件锁问题,您是否可以将其更改为使用数据库?
大多数托管解决方案允许最多250mb的SQL数据库。
数据库不仅可以帮助解决锁定问题,而且还可以让您在更糟糕的情况下更轻松地清除旧数据,日志读取将变得非常慢。
答案 3 :(得分:0)
不,不会。首先,您在每次调用时都会创建一个全新的互斥锁,因此多个线程将访问写入关键部分。其次,您甚至不在读取关键部分使用互斥锁,因此一个线程可能正在尝试读取文件而另一个线程正在尝试写入。此外,您没有在ReadLog方法中关闭流,所以一旦第一个读取请求通过您的应用程序无论如何都将无法写入任何日志条目,直到垃圾收集出现并为您关闭流...这可能需要一段时间。