简体   繁体   English

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

[英]C# file is being used by another process

I am not sure how can I solve my problem. 我不知道如何解决我的问题。 From time to time I get the error: "The process cannot access the file 'xxxx' because it is being used by another proces". 我不时会收到错误:“进程无法访问文件'xxxx',因为它正被另一个进程使用”。

Here is my method where the error happens: 这是我发生错误的方法:

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

And the error I get: 我得到的错误:

************** 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)

If you have made sure that you are genuinely opening and closing the file correctly, the most likely culprit is your virus detector. 如果您确定正确地打开和关闭文件,最可能的罪魁祸首就是您的病毒检测器。 Virus detectors are notorious for observing that a log file has changed, opening it up to search it for a virus, and then while it is being read by the virus checker, an attempt to write to the file fails. 病毒检测器因观察日志文件已更改,打开它以搜索病毒而臭名昭着,然后在病毒检查程序读取时,尝试写入文件失败。

If that's the case, then I would ask the vendor of your virus checker what their recommended workaround is. 如果是这种情况,那么我会询问您的病毒检查程序的供应商他们推荐的解决方法是什么。

  1. Use using around all your objects that are IDisposable . 使用using周围所有的对象是IDisposable using will ALWAYS call the method Dispose , even if there is an exception. 即使存在异常, using将始终调用方法Dispose
  2. You did close your reader, but did not close the filestream. 你确实关闭了你的读者,但没有关闭文件流。
  3. This code can be made much shorter, see my second example at the bottom of my answer. 这段代码可以缩短得多,请参阅我答案底部的第二个例子。

     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() + ">"); } } 

Shorter version: 更短的版本:

    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() + ">");
    }

In case of multi threading: 在多线程的情况下:

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() + ">");
    }
 }

my guess is that your FileStream (the one you're passing into your StreamReader constructor) is not getting closed 我的猜测是你的FileStream (你传递给StreamReader构造函数的那个​​)没有被关闭

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

Put that statement in a using statement, to make sure all your ends are tied 将该语句放在using语句中,以确保所有目的都绑定

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

Your method is not thread-safe. 您的方法不是线程安全的。 If you're accessing this method in a multi-threaded fashion, your threads could be attempting the file access at the same time. 如果您以多线程方式访问此方法,则您的线程可能同时尝试访问文件。 In addition to alexn's answer of properly disposing of your StreamReader, also consider using a static object outside of your method in your class and then simply locking on that before you access the file. 除了alexn正确处理StreamReader的答案之外,还要考虑在类中使用方法之外的静态对象,然后在访问文件之前简单地锁定它。

private static object lockObject = new object();

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

Either you can use "using" or you can force the Garbage collector to release all the references. 您可以使用“使用”,也可以强制垃圾收集器释放所有引用。 This has resolved my issue. 这解决了我的问题。 Review your code before applying process level or thread level changes. 在应用进程级别或线程级别更改之前检查代码。

example: 例:

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

Or: 要么:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM