gpt4 book ai didi

c# - 如何在尝试删除文件时调试 "Sharing Violation"

转载 作者:可可西里 更新时间:2023-11-01 08:33:58 28 4
gpt4 key购买 nike

我有一个多线程 C# 应用程序,它创建文件,打开它们进行处理,然后在完成后删除它们。此应用程序可以预期处理 1 - 100 个文件。有点随机(很可能归因于应用程序的多线程性质)当我尝试在处理后删除文件时遇到共享冲突。我的直觉告诉我,维克,你在尝试删除文件之前没有正确关闭/处置文件。如果每个文件都发生这种情况,我会凭直觉去做,但事实并非如此。所以,我试图找出我在哪里犯了错误。外面有人对如何调试此类异常有任何指示吗?如果有意义的话,我很乐意在文件上看到堆栈跟踪。

我将尝试展示伪代码,但是,我的问题更多是关于如何调试此类异常:

申请事件:

操作开始 += 创建新处理器。

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

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

处理器事件:

处理器完成 += Application_CleanUpProcessor。在这个方法中,我处理了处理器,处理器又处理了一个文档对象,该对象删除了文件。

最佳答案

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

  • 您的文件在本地磁盘(不是网络共享)上,并且
  • 您怀疑防病毒软件、Windows 索引或其他软件正在锁定您的代码以外的文件
  • 因此在编写测试之前,您需要一种快速的方法来验证输入/输出

您希望能够运行您的程序,并查看导致您遇到共享冲突的那个文件发生了什么。

我会这样做:

1。从 sysinternals 下载 ProcMon(10 秒)

Procmon 是一款出色的工具,您可以按顺序筛选出您希望在所有进程中看到的内容。 Link to procmon at sysinternals, from Microsoft

2。提取并运行 Procmon,添加过滤器和高亮显示(30 秒)

打开 procmon,为“路径”添加过滤器“开始于”“

Adding a filter to procmon

现在为“Result”“is”“SHARING VIOLATION”添加高亮显示

Add a Sharing Violation filter

最后,运行程序直到出现异常,然后在路径列中右键单击共享冲突的文件,然后选择“在此处包含‘<文件名>’”以删除所有其他结果。您现在可以查看导致异常的文件的所有事件...

Procmon showing who locked that file

如果您想熟悉 procmon,这里是我用来为您伪造的代码。它有一个锁定文件的副线程,以及一个尝试锁定文件的主线程。只需创建一个 C# 控制台应用程序即可。它看起来像这样:

Here's one I made earlier - the lock and lock again culprit

因此,在不到 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();
}
}

这就是所有人!

关于c# - 如何在尝试删除文件时调试 "Sharing Violation",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15450860/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com