如何试图删除文件时调试“共享违规”(How to debug “Sharing Violation”

2019-08-17 16:37发布

我有一个创建文件,打开它们进行处理多线程C#应用程序,然后将它们删除一次吃完。 此应用程序可以期待从任何地方1 - 100要处理的文件。 有点随机(最有可能归因于应用程序的多线程性质),我得到一个共享冲突时,我尝试处理后删除文件。 我的直觉说,嗯,维克,你没有正确地关闭/试图删除它之前的配置文件。 而且我会用我的直觉去,如果它发生了每一个文件,但它没有。 所以,我试图找出我犯了一个错误。 任何人在那里有关于如何调试这类异常的任何指针? 我很想看到的文件堆栈跟踪如果是有道理的。

我将试图表明伪代码,但是,我的问题是更多关于如何调试这种类型的异常:

应用程序事件:

操作启动 + =创建新的处理器。

传输文件 + = Processor.ProcessFile和新Document对象添加到处理器的文档集合(如路径,而不是文件)

操作完成 + = Processor.Aggregate文件,创建一个包含文件内容的新文件。 当此方法完成后,它调用ProcessorFinished。

处理器事件:

处理器成品 + = Application_CleanUpProcessor。 在该方法中,我处置处理器,这反过来处置文档对象,这将删除文件中的。

Answer 1:

接受你需要一个快速的方法来验证是否要花费更多的时间调试代码,或者可能编写好的测试,以证明你的代码是好的,你想要的是一个快速的方法来证明没有其他进程正在使用您的文件。 所以,让我们假设:

  • 您的文件在本地磁盘上(而不是网络共享),以及
  • 你怀疑病毒,Windows索引或别的东西被锁定比你的代码的其他文件
  • 因此,你需要一个快速的方式来限定,在输入/输出编写测试之前,

你要能够运行您的程序,看看发生了什么事该文件主要取决于你有一个共享冲突的地步。

我这样做:

从Sysinternals的1.下载procmon中(10秒)

procmon中是一个很好的工具,您可以筛选到你想看到的顺序在所有流程中发生了什么。 链接到procmon中的Sysinternals的,从微软

2.提取并运行将procmon,添加过滤器和亮点(30秒)

打开procmon中,添加一个过滤器“路径”,“开始”,“

现在添加了“结果”一大亮点“是”,“共享冲突”

最后,“‘' 这里的文件名 >’包括”运行程序,直到你得到一个异常,然后右键单击文件与共享冲突,在路径列,然后选择删除所有其他结果。 现在,您可以看到引起您的例外文件中的所有活动...

如果你想获得舒适与procmon中,这里是我伪造使用这一切都为你的代码。 它有一个侧线,其锁定的文件,一个主线程,然后试图锁定文件。 只要创建一个C#控制台应用程序和您去。 它看起来像这样:

因此,在不到2分钟就可以看到如果你的代码有过错,或别的东西。 我该用一天来确定我的COM组件使用备用文件流是事实,因为扔,当它试图用一个网络驱动器的异常。 单元测试再多就会有帮助了我。

这里是测试代码,迫使共享冲突:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using System.Threading;

internal class Program
{
    private static int lockPoint = 0;

    private static void Main(string[] args)
    {
        const string testFile = @"H:\test\test.txt";

        FileInfo testFileInfo = new FileInfo(testFile);

        if (!testFileInfo.Directory.Exists)
        {
            testFileInfo.Directory.Create();
        }

        //  Clear our example
        if (testFileInfo.Exists)
        {
            testFileInfo.Delete();
        }

        //  Create the test file
        using (FileStream fs = File.Create(testFile))
        using (StreamWriter sw = new StreamWriter(fs))
        {
            sw.WriteLine("test file content");
        }

        Task iLockTheFileFirst = new Task(() => {
            using (FileStream fsThread = File.Open(testFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                Console.WriteLine("iLockTheFileFirst: I opened the file");

                //  Set lockPoint to 1 and let main try and open the file
                Interlocked.Exchange(ref lockPoint, 1);

                //  Wait until the main thread sets lockPoint to 3
                const int ifEqualTo3 = 3;
                const int replaceWith4 = 4;
                while (Interlocked.CompareExchange(ref lockPoint, replaceWith4, ifEqualTo3) != ifEqualTo3)
                {
                    Console.WriteLine("iLockTheFileFirst: Waiting for main thread to let me finish");
                    Thread.Sleep(1000);
                }
            }
            Console.WriteLine("iLockTheFileFirst: I have closed the file");
        });
        //  Start the thread and lock the file
        iLockTheFileFirst.Start();

        //  Now spin until the lockPoint becomes 1
        const int ifEqualTo1 = 1;
        const int replaceWith2 = 2;
        //  If lockPoint is equal to 1 (i.e. the main thread wants us to finish), then move it to 2
        while (Interlocked.CompareExchange(ref lockPoint, replaceWith2, ifEqualTo1) != ifEqualTo1)
        {
            Console.WriteLine("Main thread: waiting for iLockTheFileFirst to open the file");
            Thread.Sleep(1000);
        }

        try
        {
            Console.WriteLine("Main thread: now I'll try opening the file");
            using (FileStream fsMain = File.Open(testFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                Console.WriteLine("Main thread: I opened the file, which shouldn't be possible");
            }
        }
        catch (IOException ioex)
        {
            Console.WriteLine("Main thread: IOException: " + ioex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Main thread: some other exception: " + ex.Message);
        }

        //  Set lockPoint to 3 and let other thread finish
        Interlocked.Exchange(ref lockPoint, 3);

        //  Wait for other thread to finish
        const int ifEqualTo4 = 4;
        const int replaceWith5 = 5;
        while (Interlocked.CompareExchange(ref lockPoint, replaceWith5, ifEqualTo4) != ifEqualTo4)
        {
            Thread.Sleep(10);
        }

        Console.WriteLine("Main thread: Press enter to finish");
        Console.ReadLine();
    }
}

这是所有乡亲!



文章来源: How to debug “Sharing Violation” when trying to delete a file