在我们的应用程序中,我们有一个 ASP.NET Web 服务器和一个 API 服务器来承担各种工作。在此特定工作流程中,用户上传 Web 服务器复制到网络共享的文件以供作业服务器使用。作业服务器通过每秒扫描一次 MSSQL 表中的新行来通知此情况。今年的某个时候,在集成测试期间,该流程开始随机失败:
System.IO.IOException: The process cannot access the file '\\a\\b\\c.xlsx' because it is being used by another process."
本地开发人员和质量检查人员从未遇到过此问题,但我认为这是因为他们的共享文件夹放置在各自的工作计算机上。当共享文件夹从本地文件系统移动到网络共享时,开始出现相同的异常。
我可以使用这个简短的应用程序在随机场合进行重现:
static void Main(string[] args)
{
const string DestinationDirectory = "\\\\10.122.xxx.xxx\\Testing";
var inputPath = args[0];
var filename = Path.GetFileName(inputPath);
var destinationPath = Path.Combine(DestinationDirectory, filename);
Console.WriteLine(filename);
Console.WriteLine("Copying the source file...");
File.Copy(inputPath, destinationPath, true);
Console.WriteLine("Opening the destination file...");
try
{
using var _ = File.Open(destinationPath, FileMode.Open, FileAccess.Read);
Console.WriteLine("Success!");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
如果我用这个批处理脚本运行它,我大约有十分之一的机会遇到异常。
@echo off
for /l %%x in (1, 1, 10) do (
FileShareDemo.exe "C:\a\b\c\myfile"
)
myfile
Copying the source file...
Opening the destination file...
System.IO.IOException: The process cannot access the file '\\10.122.xxx.xxx\Testing\myfile' because it is being used by another process.
at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.Strategies.FileStreamHelpers.ChooseStrategyCore(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.File.Open(String path, FileMode mode, FileAccess access)
at FileShareDemo.Program.Main(String[] args)
@echo off
set file=myfile
set source="C:\a\b\c\%file%"
set destination="\\10.122.xxx.xxx\Testing\%file%"
for /l %%x in (1, 1, 10) do (
echo Copying...
copy %source% %destination%
echo Reading...
type %destination%
REM powershell -command "Get-Content %destination% -Encoding byte -TotalCount 2"
)
执行相同的命令,不会触发错误,所以我相信它与.NET相关。
我尝试使用 Microsoft 的 Handle 实用程序来查找文件打开之前和之后的所有文件关联句柄,但应用程序太慢而无法注册它们。
Windows 上的某些东西似乎会在最短的时间内锁定新文件,解决方案是在短时间内尝试再次访问该文件。我们延迟了 5 秒,此后问题就消失了。