我在 C# winforms 中使用 fileSystemWatcher 来监视在
c:\Backup
文件夹中创建的新文件和文件夹,我的客户将文件传输到此文件夹,我的应用程序应该压缩新创建的文件和文件夹并通过电子邮件发送它们。
我对 Watcher 及其事件没有任何问题,并且工作正常。
我的问题是我如何知道将大文件复制到
c:\Backup
是否完成以便我的应用程序可以开始压缩并发送它们?
更新:我刚刚发现每个复制的文件首先引发
事件,然后在复制开始时引发Created
事件,复制完成后再次引发Changed
事件。Changed
复制完成后,它再次引发 Changed 事件。
在这里要明确一点,每次文件更改时,即数据完成写入磁盘时,您都会收到更改通知。对于未缓存的每个字节,或者仅在缓存时偶尔发生一次,都会发生这种情况。像 .Net 这样的高级框架实际上有多层缓存,包括操作系统缓存,所以你不知道有多少事件会被触发。
综上所述,不要假设它总是只有 2 个事件。这可能取决于您的特定应用程序正在写入的文件的大小。您唯一的保证是每次您确实看到事件数据已完成写入。所以你最好的选择是尝试在不共享的情况下打开它 (
FileSharing.None
) 如果它失败了它还没有完成复制。
所以在阅读了有用的评论和一些解决方法之后,我找到了一个可能不是最好的解决方案,但我认为它正在做这项工作。
async private void fileSystemWatcher1_Created(object sender, FileSystemEventArgs e)
{
listBox6.Items.Add(e.FullPath + " " + e.ChangeType);
FileInfo file = new FileInfo(e.FullPath);
if (file.Attributes != FileAttributes.Directory)
{
Action lbl = () => { listBox7.Items.Add(e.Name + " copy in progress"); };
await Task.Run(() =>
{
while (IsFileLocked(file))
{
//some code like progressbar can be here
//this.Invoke(lbl);
}
}).ConfigureAwait(true);
}
listBox7.Items.Add(e.Name + " copied!");
}
和检查文件锁定的方法(我刚从mong zhu的评论中得到):
bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
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;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}