0

当我得到:

该进程无法访问该文件,因为它正被另一个进程使用

我正在开发一个网络应用程序,所以我可以从几个不同的应用程序同时访问这个文件。

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

2 回答 2

1

当场景中有多个应用程序时,您的 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
           }
        }
    } 

我认为很好很简单。

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

于 2013-04-10T13:38:53.623 回答
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);
    }
}

但是您应该只将此类代码用作最后的手段。

于 2013-04-10T13:32:44.887 回答