【问题标题】:Want to write to a file, but may have potentially multiple writers at once, need to lock想要写入文件,但可能同时有多个写入者,需要锁定
【发布时间】:2008-09-18 15:28:21
【问题描述】:

在 asp.net Web 应用程序中,我想写入文件。这个函数会先从数据库中获取数据,然后写出平面文件。

我能做些什么来确保只发生 1 次写入,并且一旦发生写入,可能想要写入文件的其他线程在写入发生后就不会发生。

我希望仅在 15 分钟内未完成的情况下完成此写入。

我知道有一个 lock 关键字,所以我应该把所有东西都包在一个 lock 中,然后检查它是否在 15 分钟或更长时间内更新,反之亦然?

更新

工作流程:

由于这是一个 Web 应用程序,因此多个实例将是查看特定网页的人。我可以使用内置缓存系统,但是如果 asp.net 回收,重建缓存会很昂贵,所以我只想将它写到一个平面文件中。我的另一个选择是创建一个 Windows 服务,但我需要更多的工作来管理。

【问题讨论】:

  • 是否所有的写入都发生在单个应用程序的单个实例中?或者应用程序的多个实例会同时尝试写入,还是不同的应用程序会同时尝试写入?

标签: c# .net asp.net locking


【解决方案1】:

同步您的编写代码以锁定共享对象,以便只有一个线程进入块内。其他人等到当前的退出。

lock(this)
{
  // perform the write.
}

更新:我假设您有一个共享对象。如果这些是同一台机器上的不同进程,则您需要像命名互斥锁这样的东西。 Looky here for an example

【讨论】:

  • 我认为这行不通,原因我在下面解释过。
【解决方案2】:

锁定一个对象变量而不是整个实例不是更好吗?

【讨论】:

    【解决方案3】:

    写入文件的文件 I/O 操作将自动锁定文件。检查文件是否被锁定(通过尝试写入)以及是否不写入。在进行任何写入之前,请检查文件上的时间戳,看看它是否超过 15 分钟。

    afaik 你不能在没有被 Windows/whatever 锁定的情况下写入文件。

    现在剩下的就是查找如何使用 msdn 执行上述操作(抱歉,我懒得全部查找,而且我不太记得 C# 类)。 :)

    【讨论】:

    • 注意,我的答案取决于时间戳是否可靠——并不总是一个好的假设。在任何进程完成写入之后,您可以将文件保持打开状态,只是在 15 分钟内不被写入。 :)
    【解决方案4】:

    我不相信 .NET 的锁定适用于不同的进程。此外,lock(this) 只会排除在“this”的同一实例上运行该方法的其他线程——因此即使在同一进程中的其他线程也可以同时在不同的实例上运行。

    假设您的所有进程都在同一台机器上运行,文件锁定应该这样做。

    如果你在不同的机器上,你的里程可能会有所不同 - win32 声称有文件锁定,可以通过网络工作,但历史上依赖它的应用程序(想想 MSAccess)无论如何都会遇到文件损坏问题。

    【讨论】:

    • 你说得对,为了使锁起作用,你需要所有方法都使用相同的“this”实例。这里的解决方案可能是创建一个 static 虚拟对象实例来确保这一点。
    【解决方案5】:
       // try enter will return false if another thread owns the lock
       if (Monitor.TryEnter(lockObj))
       {
          try
          {
             // check last write time here, return if too soon; otherwise, write
          }
          finally
          {
             Monitor.Exit(lockobj);
          }
       }
    

    【讨论】:

    • 这与 lock(lockObj) { } 完全相同。
    【解决方案6】:

    使用文件系统锁

    像其他人建议的那样,.NET 锁在这种情况下的用途有限。 代码如下:

    FileInfo fi = new FileInfo(path);
    if (fi.Exists
        && (DateTime.UtcNow - fi.LastWriteTimeUtc < TimeSpan.FromMinutes(15)) {
      // file is fresh
      return;
    }
    
    FileStream fs;
    try {
      fs = new FileStream(
        path, FileMode.Create, FileAccess.Write, FileShare.Read);
    } catch (IOException) {
      // file is locked
      return;
    }
    
    using (fs) {
      // write to file
    }
    

    这将跨线程进程工作。

    【讨论】:

      【解决方案7】:

      你们应该考虑Mutex。它可以在多个线程和进程之间进行同步。

      【讨论】:

        猜你喜欢
        • 2017-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-15
        • 1970-01-01
        • 1970-01-01
        • 2015-01-26
        • 2010-09-19
        相关资源
        最近更新 更多