3

我有两个 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();
}

我的问题是,上面的代码是否足以防止锁定在网络花园环境中?

编辑1:脏读没关系。 编辑 2:使用 new Mutex(false, "LogFileMutex") 创建 Mutex,关闭 StreamWriter

4

4 回答 4

8

听起来你试图实现一个基本的队列。为什么不使用可以保证可用性的队列。您可以将消息放入 MSMQ,然后实现一个 Windows 服务,该服务将从队列中读取并将消息推送到数据库。如果写入数据库失败,您只需将消息留在队列中(尽管您将希望处理位置消息,因此如果失败导致数据错误,您不会陷入无限循环)

这将消除所有锁定问题,并为您提供保证交付给您的读者......

于 2009-01-10T15:22:36.700 回答
2

您还应该处理您的互斥锁,因为它派生自 WaitHandle,并且 WaitHandle 实现了 IDisposable:

using (Mutex FileLock = new Mutex(true, "LogFileMutex"))
{
    // ...
}

此外,也许考虑一个比“LogFileMutex”更独特的名称(也许是 GUID),因为另一个不相关的进程可能会无意中使用相同的名称。

于 2009-01-10T15:41:28.893 回答
1

在基于 Web 的环境中执行此操作,您将遇到很多文件锁定问题,您可以将其更改为使用数据库吗?

大多数托管解决方案最多允许 250mb 的 SQL 数据库。

数据库不仅可以帮助解决锁定问题,还可以让您更轻松地清除旧数据,但经过一段时间后,日志读取会变得非常慢。

于 2009-01-10T12:01:55.090 回答
1

不,不会的。首先,您将在每次调用时创建一个全新的互斥锁,因此多个线程将访问写入临界区。其次,您甚至没有在读取临界区中使用互斥锁,因此一个线程可能正在尝试读取文件,而另一个线程正在尝试写入。此外,您没有在 ReadLog 方法中关闭流,因此一旦第一个读取请求通过您的应用程序将无法写入任何日志条目,直到垃圾收集出现并为您关闭流......这可能需要一段时间。

于 2009-01-10T12:25:14.997 回答