另一个进程正在使用C#文件

时间:2013-04-29 18:06:36

标签: c# file io locking

我不知道如何解决我的问题。我不时得到错误: “该进程无法访问文件'xxxx',因为它正被另一个进程使用”。

这是我发生错误的方法:

private static void write_history(int index, int time_in_sec, int[] sent_resources)
        {
            string filepath = "Config\\xxx.txt";
            int writing_index = 0;

            if (File.Exists(filepath))
            {
                System.Threading.Thread.Sleep(5000);
                StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read));
                string temp = reader.ReadToEnd();
                reader.Close();

                for (int i = 0; i < 20; i++)
                {
                    if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
                    {
                        writing_index = i;
                        break;
                    }
                }
            }

            System.Threading.Thread.Sleep(5000);
            // write to the file
            StreamWriter writer = new StreamWriter(filepath, true);
            writer.WriteLine("<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
            writer.Close();
        }

我得到的错误:

************** Exception Text **************
System.IO.IOException: The process cannot access the file 'Config\\xxx.txt' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)

5 个答案:

答案 0 :(得分:9)

如果您确定正确地打开和关闭文件,最可能的罪魁祸首就是您的病毒检测器。病毒检测器因观察日志文件已更改,打开它以搜索病毒而臭名昭着,然后在病毒检查程序读取时,尝试写入文件失败。

如果是这种情况,那么我会询问您的病毒检查程序的供应商他们推荐的解决方法是什么。

答案 1 :(得分:3)

  1. using的所有对象周围使用IDisposableusing将始终调用方法Dispose,即使存在异常。
  2. 你确实关闭了你的读者,但没有关闭文件流。
  3. 这段代码可以缩短得多,请参阅我答案底部的第二个例子。

    private static void write_history(int index, int time_in_sec, int[] sent_resources)
    {
        string filepath = "Config\\xxx.txt";
        int writing_index = 0;
    
        if (File.Exists(filepath))
        {
            System.Threading.Thread.Sleep(5000);
            using(FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)
            using(StreamReader reader = new StreamReader(stream))
            {
                 string temp = reader.ReadToEnd();
            }
    
            for (int i = 0; i < 20; i++)
            {
                if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
                {
                    writing_index = i;
                    break;
                }
            }
        }
    
        System.Threading.Thread.Sleep(5000);
        // write to the file
        using(StreamWriter writer = new StreamWriter(filepath, true))
        { 
             writer.WriteLine("<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
        }
    }
    
  4. 更短的版本:

        private static void write_history(int index, int time_in_sec, int[] sent_resources)
        {
            string filepath = "Config\\xxx.txt";
            int writing_index = 0;
    
            if (File.Exists(filepath))
            {
                System.Threading.Thread.Sleep(5000);
                string temp = File.ReadAllText(filepath);
    
                for (int i = 0; i < 20; i++)
                {
                    if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
                    {
                        writing_index = i;
                        break;
                    }
                }
            }
    
            System.Threading.Thread.Sleep(5000);
            // write to the file
            File.WriteAllText(filepath, "<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
        }
    

    如果是多线程:

    private static readonly object _syncLock = new object();
    
    private static void write_history(int index, int time_in_sec, int[] sent_resources)
    {
       lock(_syncLock)
       {
            string filepath = "Config\\xxx.txt";
            int writing_index = 0;
    
            if (File.Exists(filepath))
            {
                System.Threading.Thread.Sleep(5000);
                string temp = File.ReadAllText(filepath);
    
                for (int i = 0; i < 20; i++)
                {
                    if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
                    {
                        writing_index = i;
                        break;
                    }
                }
            }
    
            System.Threading.Thread.Sleep(5000);
            // write to the file
            File.WriteAllText(filepath, "<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
        }
     }
    

答案 2 :(得分:1)

我的猜测是你的FileStream(你传递给StreamReader构造函数的那个​​)没有关闭

StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read));

将该陈述放入使用陈述中,以确保所有目的都结束

using(StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
    //the using statement will handle the closing for you
}

答案 3 :(得分:0)

您的方法不是线程安全的。如果您以多线程方式访问此方法,则您的线程可能同时尝试访问文件。除了alexn正确处理StreamReader的答案之外,还要考虑在类中使用方法之外的静态对象,然后在访问文件之前直接锁定它。

private static object lockObject = new object();

private static void write_history(int index
{
    lock(lockObject)
    {
        // Access file here
    }
}

答案 4 :(得分:0)

您可以使用“使用”,也可以强制垃圾收集器释放所有引用。 这解决了我的问题。在应用流程级别或线程级别更改之前,请检查您的代码。

示例:

using(StreamWriter writer....)
{
  Your Code....
}
this.deleteFiles(filepath);

或者:

GC.Collect();
this.deleteFiles(filepath);