等待资源可用

本文关键字:资源 等待 | 更新日期: 2023-09-27 18:08:31

当我得到:

时,是否有一个好方法来执行此代码(等待直到该文件解锁):

进程不能访问该文件,因为它正在被另一个进程使用

我在一个web应用程序上工作,所以我可以从几个不同的应用程序并发访问这个文件。

bool isLock = false;
do
{
    try
    {
        File.WriteAllText(path, value, Encoding.Unicode);
        isLock = false;
    }
    catch
    {
        Thread.Sleep(30);
        isLock = true;
    }    
}while (isLock);

等待资源可用

当场景中有多个应用程序时,lock变量是没有用的。

不如测试一下你是否可以File。OpenWrite,然后写入文件。如果无法访问文件循环并等待或写入临时文件,则启动另一个线程循环并等待,直到临时文件可以合并。

也许更好的方法是立即存储到temp,并让看门狗写入您的存储文件。

public void SomeWhereInYourWebServerApplication
    {           
        FileSystemWatcher fsw = new FileSystemWatcher("tempfolder");
        fsw.Created += fsw_Created;
        // save new entries to tempfolder
    }
    void fsw_Created(object sender, FileSystemEventArgs e)
    {
      foreach (string file in Directory.GetFiles("tempfolder"))
        {
         try
           {
            string fileText = File.ReadAllText(file);
            File.AppendAllText("myStorage.txt", fileText);
            File.Delete(file);
           }
          catch
           {
              // for me it's ok when we try to append the file the next time
              // something new is coming
           }
        }
    } 

很好很简单。

当涉及到文件时,不要忘记做适当的异常处理。

如果你绝对必须这样做,并且你无法控制使用该文件的应用程序,那么你的代码就差不多了。

它只需要稍微健壮一点:

public static bool TryWriteText(string path, string text, TimeSpan timeout)
{
    Contract.Requires(path != null); // Or replace with: if (path == null) throw new ArgumentNullException("path");
    Contract.Requires(text != null); // Or replace with: if (text == null) throw new ArgumentNullException("text");
    Stopwatch stopwatch = Stopwatch.StartNew();
    while (stopwatch.Elapsed < timeout)
    {
        try
        {
            File.WriteAllText(path, text);
            return true;
        }
        catch (IOException){} // Ignore IOExceptions until we time out, then return false.
        Thread.Sleep(100); // 100ms is rather short - it could easily be 1000 I think.
    }                      // Perhaps this should be passed in as a parameter.
    return false;
}

在超时时重新抛出最后一个IOException的替代版本(这可能更好,因为您没有隐藏所有异常):

public static void TryWriteText(string path, string text, TimeSpan timeout)
{
    Contract.Requires(path != null); // Or replace with: if (path == null) throw new ArgumentNullException("path");
    Contract.Requires(text != null); // Or replace with: if (text == null) throw new ArgumentNullException("text");
    Stopwatch stopwatch = Stopwatch.StartNew();
    while (true)
    {
        try
        {
            File.WriteAllText(path, text);
        }
        catch (IOException)
        {
            if (stopwatch.Elapsed > timeout)
                throw;
        }
        Thread.Sleep(100);
    }
}