C#中随机抛出的IO异常

时间:2010-07-26 19:54:54

标签: c# file exception

我一直致力于为我工作的公司存档旧客户数据的程序。程序将数据从工作服务器复制到本地计算机,创建所有数据的.zip文件,然后将其复制到存档服务器。

完成所有操作后,它会删除原始文件和本地副本。每隔一段时间,程序就会出错,因为它无法从我的计算机上删除本地副本。它不会错误地拉动每个不同的文件夹。在完成300个之后或5之后我会出错。它会抛出以下3个错误中的一个,“目录不为空”,“文件正被另一个进程使用”或“访问文件被拒绝”。我尝试使用强制垃圾收集将文件属性设置为正常,并手动结束winzip进程。

我真的不明白为什么它有时会这样做。我是我的计算机上的管理员,它应该能够删除文件。我想其他东西必须使用它,但除了Visual Studio中的程序之外,我的机器上应该没有其他任何东西使用它。感谢。

以下是清除方法,它不删除文件和拉链文件的方法。

[MethodImplAttribute(MethodImplOptions.NoInlining)]
    static void CleanUp(SqlConnection Connection, string jNumber, DirectoryInfo dir, bool error, string prefix)
    {
        if (!error | (!error & emptyFolder))
        {
            try
            {
                SqlCommand updateJob = new SqlCommand(string.Format("update job set archived = 1 where job = {0}", jNumber), sdiConnection);
                updateJob.ExecuteNonQuery();
            }
            catch
            {
                WriteToLog("SQL Error: " + jNumber, "There was an error changing the archive bit to 1 after the job has been archived");
            }

            try
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            catch
            {
                WriteToLog("Error cleaning up after processing job", "There was an error garbage collecting.");
            }


            try
            {
                //path of the temporary folder created by the program
                string tempDir = Path.Combine(Path.Combine(System.Environment.CurrentDirectory, "Temp"), jNumber);
                //path of the destination folder
                string destDir = Path.Combine(dir.ToString(), jNumber);
                //SetFileAttributes(tempDir);


                try
                {
                    File.Delete(tempDir + ".zip");
                }
                catch (System.IO.IOException)
                {
                    File.Delete(tempDir + ".zip");
                }
                try
                {
                    Directory.Delete(destDir, true);
                }
                catch (System.IO.IOException)
                {
                    Directory.Delete(destDir, true);
                }
                try
                {
                    Directory.Delete(tempDir, true);
                }
                catch (System.IO.IOException)
                {
                    Directory.Delete(tempDir, true);
                }

            }
            catch
            {

                WriteToLog("File Error: " + jNumber, "There was an error removing files and/or folders after the job has been archived. Please check the source server and destination server to make sure everything copied correctly. The archive bit for this job was set.");
                Directory.Delete(Path.Combine(System.Environment.CurrentDirectory, "Temp"), true);
                Directory.CreateDirectory(Path.Combine(System.Environment.CurrentDirectory, "Temp"));
            }
        }


static bool ZipJobFolder(string jNumber, string jPath)
    {
        try
        {
            string CommandStr = @"L:\ZipFiles\winzip32.exe";
            string parameters = "-min -a -r \"" + jNumber + "\" \"" + jPath + "\"";

            ProcessStartInfo starter = new ProcessStartInfo(CommandStr, parameters);
            starter.CreateNoWindow = true;
            starter.RedirectStandardOutput = false;
            starter.UseShellExecute = false;

            Process process = new Process();
            process.StartInfo = starter;
            Console.WriteLine("Creating .zip file");
            process.Start();
            process.WaitForExit();

            Process[] processes;
            string procName = "winzip32.exe";
            processes = Process.GetProcessesByName(procName);
            foreach (Process proc in processes)
            {
                Console.WriteLine("Closing WinZip Process...");
                proc.Kill();
            }

        }
        catch
        {
            WriteToLog(jNumber, "There was error zipping the files of this job");
            return false;
        }
        return true;
    }

4 个答案:

答案 0 :(得分:1)

我注意到使用Windows资源管理器的这种行为,同时删除了包含大量文件和子文件夹的大文件夹。但等了一会儿然后再次删除,似乎工作正常。

正因为如此,我一直认为这是操作系统的一个不稳定的行为。

虽然这不是一个解决方案,但您可以尝试删除这些文件之前让应用程序休眠一小段时间,然后查看是否仍然出现错误。

如果错误消失,它似乎与某些时间问题有关。我本人想知道问题的根源。

评论者指出反病毒程序。这是有道理的,如果这是真的那么你需要编写一些代码来检查文件是否在尝试删除之前被锁定。如果它被锁定,然后再睡一会儿,然后再次检查,直到它不再被锁定,你可以继续删除它。

你需要注意不要陷入无限的竞争状态。

修改 有一个相关的问题是关于How to best wait for a filelock to release检查它的想法。

<强> EDIT2: 这是另一种可能的解决方案Wait until file is unlocked in .Net

答案 1 :(得分:1)

您很可能会遇到共享冲突 - 删除无法获取独占文件句柄。这种情况的一种方式是AV软件被触发,并且在调用删除之前没有完成扫描。也可能是WinZip进程尚未完全死亡。

处理它的几种方法: 1)失败时,睡几秒钟&amp;再试一次。 2)我可能不会使用WinZip&amp;而是使用ZipStorer(http://zipstorer.codeplex.com/)。它将在此过程中压缩文件,您不必执行kill步骤&amp;你将有更多细粒度的控制。您也可以通过旋转多个线程来并行执行拉链。

答案 2 :(得分:0)

我发现有一件事有帮助,就是不要尝试在单个File.Move或File.Copy调用中创建临时文件和目录。而是手动创建父目录,从最高级别开始并向下工作。最后,当所有父目录都存在时,移动或复制文件。

答案 3 :(得分:0)

防病毒软件可能是一个问题,因为如果防病毒软件当前正在读取您的文件,那将导致这一点,说实话我已经看到这种情况多次出现在使用.NET框架时,我只是在处理循环并尝试执行任何文件操作,直到它不再抛出异常。如果当前正在复制文件或正在内核缓冲区中注册文件,如果实现某种观察器,也会发生这种情况。