System.IO.IOException:进程无法访问文件'.txt',因为它正由另一个进程使用

时间:2015-04-29 10:21:02

标签: c# file io streamwriter

我正在使用下一个代码来记录Web应用程序的错误。

using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
{                
myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));      

}

有时,以下异常'System.IO.IOException:进程无法访问文件'.txt',因为它正被另一个进程使用。扔了。

我认为这是由多个Web应用实例同时引起的。你能帮我解决这个问题吗?

编辑:我必须为我记录的每个方法添加:

日期 - 方法X开始。

日期 - Exception.Message(未找到表格或其他错误)

日期 - 方法X已停止。

当出现此错误时,仅记录此信息:

Date - System.IO.IOException:进程无法访问文件'.txt',因为它正由另一个进程使用。

4 个答案:

答案 0 :(得分:4)

可悲的是,Windows不允许等待文件锁定。为了解决这个问题,所有应用程序都必须创建一个锁,所有相关的进程都可以检查。

使用此代码只会阻止单个进程中的线程访问该文件:

/* Suitable for a single process but fails with multiple processes */
private static object lockObj = new Object();
lock (lockObj)
{
    using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
    {                
        myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));      
    }
}

为了锁定多个进程,需要使用Mutex锁。这为其他进程可以检查的锁提供了一个名称。它的工作原理如下:

/* Suitable for multiple processes on the same machine but fails for
   multiple processes on multiple machines */
using (Mutex myMutex = new Mutex(true, "Some name that is unlikly to clash with other mutextes", bool))
{
    myMutex.WaitOne();
    try
    {
        using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
        {
            myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
        }
    }
    finally
    {
        myMutex.ReleaseMutex();
    }

}

我不认为可以从远程计算机访问互斥锁,所以如果你在文件共享上有一个文件并且你试图从多台机器上的进程写入它,那么你可能最好在编写一个服务器组件承载文件以在进程之间进行调解的机器。

答案 1 :(得分:3)

假设您需要每个线程最终写入日志,您可以lock关键部分

private static object fileLock = new Object();
...
lock (fileLock)
{
    using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
    {                
        myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));      

    }
}

这意味着在任何给定时间只有1个线程可以写入文件,其他线程被阻塞,直到当前线程退出临界区(此时文件锁将被删除)。

此处需要注意的一点是lock每个进程 ,因此如果您的网站正在运行Web场/花园的上下文,那么您需要查看 system -wide锁定机制,即Mutexes

答案 2 :(得分:3)

您的Web服务器将在多个线程中运行请求。如果两个或多个请求必须同时记录异常,这将导致您看到的异常。

您可以按照James的建议锁定该部分,也可以使用可以为您处理多线程问题的日志框架,例如Lgo4netNLog

答案 3 :(得分:-1)

我已将此代码添加到我的班级:

 public static bool IsFileLocked(FileInfo file)
        {
            FileStream stream = null;

            try
            {
                stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
            }
            catch
            {
                return true;
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }

            return false;
        }

现在我的LogToFile方法是这样的:

while (IsFileLocked(fi))
            {
            }

            using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
            {
                if (displayTime == true)
                    myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10}{3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
                else
                    myStream.WriteLine(string.Format("{0, -70}{1, -10}{2} ", guid, StringEnum.GetStringValue(enumMsg), sText));                
            }

我希望这会奏效。