【问题标题】:Replacing file content without readers clients access interruption在没有阅读器客户端访问中断的情况下替换文件内容
【发布时间】:2011-05-21 15:37:57
【问题描述】:

有一项服务不断将新内容写入文件:

using (var stream = File.Create(FileName))     // overwrites the file
{
    stream.Write(data, 0, data.Length);
}

多个阅读器(包括从该文件呈现其内容的网络应用程序)不断访问该文件。我无法控制读者客户端代码。该文件应始终可供读者访问。更重要的是,他们应该看到整个内容,而不是正在写入文件的内容。

任何类似的技术:

using (var stream = File.Create(FileName + ".tmp"))
{
    stream.Write(data, 0, data.Length);
}

File.Delete(FileName);
File.Move(FileName + ".tmp", FileName);

可能导致网页上缺少内容(有一定的可能性)。并且服务有时会抛出IOException 异常,并显示消息“该进程无法访问该文件,因为它正被另一个进程使用”。

问题是:如何在不中断读者客户端访问的情况下不断更换文件内容?

【问题讨论】:

  • 我很确定这是不可能的。
  • 通过使用全局互斥锁同步对文件的读取访问?
  • @Tergiver:不幸的是,无法控制阅读器客户端代码。
  • 您的阅读器代码是如何托管 IIS、服务、桌面应用程序或其他东西的?

标签: c# concurrency filesystems writer


【解决方案1】:

在 IIS 中,您可以调整 this module(我写的完全公开)将同步注入到读取请求中。您可以通过继承 InterceptingHandler 并添加如下代码来做到这一点:

SychronizingHandler : InterceptingHandler
{
    // ...

    Semaphore mySemaphore;

    protected override bool PreFilter(System.Web.HttpContext context)
    {
        context.RewritePath("myFilePath");
        if( mySemaphore == null)
        {
            bool created;
            mySemaphore = new Semaphore(100, 0, "semphoreName", out created);
        }

        if( mySemaphore != null)
        {
            mySemaphore.WaitOne();
        }
        reutrn true;
    }

    // note this function isn't in the base class
    // you would need to add it  and call it right after the call to
    // innerHandler.ProcessRequest
    protected override void PostFilter(System.Web.HttpContext context) 
    {
        mySemaphore.Release();
        return;
    }

    protected virtual void OnError(HttpContext context, Exception except)
    {
        mySemaphore.Release();
        return base.OnError(context, except);
    }

桌面应用程序有点棘手,因为它取决于应用程序的实现细节。希望在这种情况下,您有办法扩展它并添加同步。

正如 Fun 在 cmets 中指出的那样,您还可以在预过滤器中进行条件重写,这样您就不会尝试访问正在写入的文件,这是一个非常好的主意。

【讨论】:

  • 如果桌面应用程序能够直接从 IIS 读取,这可能会起作用。或者,您可以让句柄在写入文件 B 时为文件 A 提供服务,并在写入文件 A 时为文件 B 提供服务。这样,您将避免锁定时间过长。
  • 感谢您的回答。不幸的是,我无法控制阅读器客户端代码。
猜你喜欢
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2018-08-19
相关资源
最近更新 更多