尝试删除.json文件时出现“System.IO.IOException”

'System.IO.IOException' when trying to delete .json files

提问人:Golden_Eagle 提问时间:3/28/2023 最后编辑:Golden_Eagle 更新时间:3/28/2023 访问量:59

问:

我正在尝试创建一个系统来删除一组文件夹,每个文件夹中都有一个.json文件(以及一堆其他文件/子目录)。但是,每次我尝试时,总会有一个随机的.json文件无法删除,因为另一个进程正在访问该文件。在有人因为被问到很多问题而删除这篇文章之前,我已经尝试了我读过的所有内容。我尝试将目录的 FileAttributes 设置为正常(当我遇到其他未链接到.json文件的目录出现相同问题时,这有效),我尝试将访问目录的线程设置为后台线程,以确保在应用程序停止后没有一个仍在运行,确保在运行程序之前关闭了文件资源管理器, 设置每个流的文件访问权限,将每个文件保存到 ReadWrite,释放写入保存 (.json) 文件而不是关闭它的 StreamWriter...没有任何效果,我没有想法。此时,只有在删除.json文件时,我才会出现此异常。我还错过了什么?

删除所有类型的每个文件的函数(嵌套函数不是错别字):

    public static void DeleteBrains()
    {
        Console.WriteLine("Resetting brains...");

        Dictionary<int, Thread> threads = new Dictionary<int, Thread>();
        for (int i = 0; i < 100; i++)
        {
            DeleteDirProtector(i);
        }
        StartThreads(threads, false);
        
        void DeleteDirProtector(int i)
        {
            Thread thread = new Thread(() => DeleteDir(i));
            threads.Add(i, thread);
        }
        void DeleteDir(int i)
        {
            string CurrentDir = $@"{DebugFolderPath}\Brain {i}";
            if (Directory.Exists(CurrentDir))
            {
                Console.WriteLine($"Deleting Brain {i}...");
                File.SetAttributes(CurrentDir, FileAttributes.Normal);
                string[] directories = Directory.GetDirectories(CurrentDir);
                string[] files = Directory.GetFiles(CurrentDir);
                for (int j = 0; j < directories.Length; j++)
                {
                    File.SetAttributes(directories[j], FileAttributes.Normal);
                }
                for (int j = 0; j < files.Length; j++)
                {
                    File.SetAttributes(files[j], FileAttributes.Normal);
                }
                Directory.Delete(CurrentDir, true);
            }
        }

保存每个.json文件的函数:

    public void SaveBrain(bool isUpdate)
    {
        BrainSaveString = JsonConvert.SerializeObject(this, Formatting.Indented);
        string path = "";
        if (isUpdate)
        {
            path = BrainSavePath2;
        }
        else if (!isUpdate)
        {
            path = BrainSavePath;
        }
        FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
        using (StreamWriter sw = new StreamWriter(stream))
        {
            sw.Write(BrainSaveString);
            sw.Dispose();
        }
    }

这可能无关紧要,但这是 StartThreads() 方法:

    public static void StartThreads(Dictionary<int, Thread> threads, bool isBackground)
    {
        int threadCount = threads.Count;

        for (int i = 0; i < threadCount; i++)
        {
            try
            {
                if (threads[i].ThreadState == ThreadState.Unstarted)
                {
                    while (!StartThread(threads[i], false, isBackground)){}
                }
            }
            catch (KeyNotFoundException) { }
        }
        while (threads.Count > 0) 
        {
            for(int i = 0; i < threadCount; i++)
            {
                try
                {
                    if (threads[i].ThreadState == ThreadState.Stopped)
                    {
                        threads.Remove(i);
                    }
                }
                catch (KeyNotFoundException) { }
            }
        }
    }

编辑:StartThread()(根据要求):

    public static bool StartThread(Thread thread, bool ShouldRunAnyway, bool isBackground)
    {
        bool shouldStartThread = false;
        if (NumberOfThreads_ < NumberOfProcessors * 3)
        {
            shouldStartThread = true;
        }
        else
        {
            if (ShouldRunAnyway)
            {
                shouldStartThread = true;
            }
        }
        if (shouldStartThread)
        {
            thread.IsBackground = isBackground;
            thread.Start();
            lock (AllThreadsBeingUsed)
            {
                AllThreadsBeingUsed.Add(thread);
            }
        }
        
        return shouldStartThread;
    }
C# JSON 多线程 IO IOException

评论

0赞 stuartd 3/28/2023
您是否尝试过从 AV 扫描中排除该文件夹?
0赞 Golden_Eagle 3/28/2023
@stuartd 我想这是我唯一没有尝试过的事情
0赞 Graffito 3/28/2023
缺少 StartThread 过程的代码。在什么情况下,此过程返回 false?如果由于某种原因返回 false,则线程可能会被复制,但会关闭一次。
0赞 Golden_Eagle 3/28/2023
@Graffito StartThread() 检查任何给定时间的活动线程数是否小于运行程序的计算机上存在的处理器数的三倍(我的 PC 有 8 个,因此在我的情况下为 24 个)。如果少于此值,则返回 true,并创建一个新线程来执行下一个函数。如果没有更少,除非我做一个异常(在这种情况下我没有),否则它会返回 false(并且不会创建新的线程)。它应该只创建一个线程一次,然后移动到字典中的下一个线程。不过我会发布代码。
1赞 stuartd 3/28/2023
您可以尝试使用进程资源管理器来查看哪个进程实际正在使用该文件

答: 暂无答案