等到资源可用?

时间:2013-04-10 12:58:35

标签: c# asp.net

当我得到这个代码时,有一个很好的方法,(等到这个文件被解锁):

该进程无法访问该文件,因为该文件正由另一个进程

使用

我正在开发一个Web应用程序,因此我可以从多个不同的应用程序同时访问此文件。

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

2 个答案:

答案 0 :(得分:1)

当场景中有多个应用程序时,您的锁定变量无用。

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

也许更好的方法是将immediatley存储到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
           }
        }
    } 

我觉得很好很简单。

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

答案 1 :(得分:0)

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

只需要稍微强一些:

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);
    }
}

但是你应该只使用这些代码作为最后的手段。