【发布时间】:2020-11-09 16:22:21
【问题描述】:
我构建了一个控制台应用程序,用于监控 Windows 2019 服务器上的一组文件夹,并使用相同的文件名将所有新创建的 .txt 文件复制到另一个文件夹。到目前为止,它适用于基本功能。现在我必须处理大多数情况下这些文件很大并且需要几分钟才能完成创建的事实。我浏览了几篇 SO 帖子并拼凑了以下代码来尝试完成此操作:
using System;
using System.IO;
namespace Folderwatch
{
class Program
{
static void Main(string[] args)
{
string sourcePath = @"C:\Users\me\Documents\SomeFolder";
FileSystemWatcher watcher = new FileSystemWatcher(sourcePath);
watcher.EnableRaisingEvents = true;
watcher.IncludeSubdirectories = true;
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Created += new FileSystemEventHandler(OnCreated);
}
// Define the event handlers.
private static void OnCreated(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is created.
FileInfo file = new FileInfo(e.FullPath);
string wctPath = e.FullPath;
string wctName = e.Name;
string createdFile = Path.GetFileName(wctName);
string destPath = @"C:\Users\SomeOtherFolder";
string sourceFile = wctPath;
string destFile = Path.Combine(destPath, createdFile);
WaitForFile(file);
File.Copy(sourceFile, destFile, true);
}
public static bool IsFileLocked(FileInfo file)
{
try
{
using (FileStream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None))
{
stream.Close();
}
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
//file is not locked
return false;
}
public static void WaitForFile(FileInfo filename)
{
//This will lock the execution until the file is ready
//TODO: Add some logic to make it async and cancelable
while (!IsFileLocked(filename)) { }
}
}
}
我在OnCreated 方法中尝试做的是检查并等待文件创建完成,然后将文件复制到另一个目的地。我似乎不知道我在用 WaitForFile(file) 行做什么 - 如果我注释掉该行并且文件创建是即时的,则文件会按预期复制。如果我使用WaitForFile 行,则不会发生任何事情。我从 SO 上的其他帖子中获取了 IsFileLocked 和 WaitForFile 方法,但我显然没有正确实现它们。
我已经注意到这个 Powershell 版本 Copy File On Creation (once complete),我不确定这里的答案是否可以为我指明正确的方向 b/c 我对 PS 的了解甚至比对 C# 的了解还要少。
编辑#1:我应该在接受答案之前测试更长时间 - 我认为我们已经接近但在程序运行大约一分钟后,我在程序崩溃之前收到以下错误:
未处理的异常。 System.IO.IOException:进程无法访问 文件 'C:\Users\me\Dropbox\test1.log' 因为它正在被另一个进程使用。在 System.IO.FileSystem.CopyFile(字符串 sourceFullPath,字符串 destFullPath,布尔覆盖)在 Folderwatch.Program.OnCreated(Object source, FileSystemEventArgs e) in C:\用户\我\OneDrive - Development\Source\repos\FolderWatchCG\FolderWatchCG\Program.cs:line 61 在 System.Threading.Tasks.Task.c.b__139_1(对象 州)在 System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
对此的任何建议将不胜感激。当我进一步分析这些文件夹中的文件时,其中一些是实时写入的日志文件,因此可能是文件在实际完成之前被写入了数小时。我想知道NotifyFilter 是否会以某种方式在这里发挥作用?
【问题讨论】:
-
我看到了一个可能的失败场景——如果你决定复制一个文件并且其他东西开始写入它,你可能会得到这个错误。如果您指出第 61 行在哪里,会更容易弄清楚。
-
第 61 行是
File.Copy方法行(请参阅下面来自 41686d6564 的答案中的OnCreated方法)
标签: c# filesystemwatcher