4

我不确定如何解决我的问题。有时我会收到错误消息:“该进程无法访问文件'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)
4

5 回答 5

9

如果您确定您确实正确地打开和关闭了文件,那么最有可能的罪魁祸首就是您的病毒检测器。病毒检测器因发现日志文件已更改而臭名昭著,将其打开以搜索病毒,然后在病毒检查器读取该文件时,尝试写入该文件失败。

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

于 2013-04-29T18:22:14.843 回答
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() + ">");
        }
    }
    

较短的版本:

    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() + ">");
    }
 }
于 2013-04-29T18:14:04.777 回答
1

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

private static object lockObject = new object();

private static void write_history(int index
{
    lock(lockObject)
    {
        // Access file here
    }
}
于 2013-04-29T18:14:07.497 回答
1

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

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

将该语句放在 using 语句中,以确保您的所有目的都绑定

using(StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
    //the using statement will handle the closing for you
}
于 2013-04-29T18:12:41.663 回答
0

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

例子:

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

或者:

GC.Collect();
this.deleteFiles(filepath);
于 2014-01-16T10:02:31.437 回答