每当用户在修改文件后保存文件时,我正在使用FileSystemWatcher
中的C#
类来跟踪文件上的更改。
FileSystemWatcher watcher = new FileSystemWatcher()
{
Path = DIR_NAME,
NotifyFilter = NotifyFilters.LastWrite |
NotifyFilters.CreationTime |
NotifyFilters.LastAccess,
Filter = "*.pdf",
IncludeSubdirectories = true,
EnableRaisingEvents = true
};
watcher.Changed += OnChanged;
但是,我要跟踪的文件是通过编程方式创建的,如下所示:
FileStream stream = FileUtil.CreateNewFile(filePath); // Creates a file
file.WriteFileToStream(stream); // Writes into the file
理想情况下,我的代码应按以下方式运行:
OnChanged
,即我希望OnChanged
处理程序代码仅在真实用户对其进行修改并保存后才执行。 但是,只要以编程方式将文件写入文件,即在以下行中,它就会被触发:
file.WriteFileToStream(stream);
从技术上讲,这是正确的行为,因为它正在跟踪文件中的更改。但是,我的业务案例不允许在最初创建并写入文件时执行OnChanged
处理程序代码。
我的问题是,是否有一种解决方法可以在以编程方式创建并首次写入文件时跳过OnChanged
调用?
注意:
FileSystemWatcher
。因此,创建文件后我无法注册它。
watcher.EnableRaisingEvents = false;
CreateFile();
watcher.EnableRaisingEvents = true;
答案 0 :(得分:1)
方法一:
方法二:
创建文件后,使用OnCreated()
事件处理程序将文件名添加到filesToIgnore
列表中。
在OnChanged
事件处理程序中,检查filesToIgnore
列表中是否包含文件名。如果是这样,请将其从列表中删除(以备下次处理),然后从处理程序中返回。
private List<string> filesToIgnore = new List<string>();
private void OnCreated(object source, FileSystemEventArgs file)
{
filesToIgnore.Add(file.Name);
}
private void OnChanged(object source, FileSystemEventArgs file)
{
if(filesToIgnore.Contains(file.Name))
{
filesToIgnore.Remove(file.Name);
return;
}
// Code to execute when user saves the file
}
此方法假定OnCreated()
总是在OnChanged().
之前触发
答案 1 :(得分:0)
这是一个棘手的情况,除了检查文件是否已锁定(假设文件具有读取或写入锁定)之外,您无能为力
public bool IsFileLocked(string fileName)
{
try
{
using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
return false;
}
}
catch (IOException)
{
//the file is unavailable
return true;
}
}
前提是获取更新时,请检查文件是否已锁定,如果未锁定,则可以松散假定其已关闭。
尽管有些事情要考虑
FileAccess.Read
,所以这在只读文件上不会失败。 FileSystemWatcher
删除事件,在某些情况下不能总是依靠它,请阅读文档以了解为什么可以删除事件以及如何修复它们。在这种情况下,您可能需要进行长时间的投票和一些逻辑来选择散乱的人(取决于您的情况)答案 2 :(得分:0)
我在OnChanged
处理程序中添加了以下代码,它似乎按预期工作。
private void OnChanged(object source, FileSystemEventArgs file)
{
if (file.ChangeType == WatcherChangeTypes.Created)
return;
FileInfo fileInfo = new FileInfo(file.FullPath);
if (fileInfo.CreationTime == fileInfo.LastWriteTime)
return;
// Handle the Changed event
...
}
但是,我不确定是否丢失了会导致这种情况中断的内容。有什么想法吗?
答案 3 :(得分:0)
以下扩展方法仅允许处理用户操作中的事件:
public static void OnChangedByUser(this FileSystemWatcher fsw,
FileSystemEventHandler handler)
{
const int TOLERANCE_MSEC = 100;
object locker = new object();
string fileName = null;
Stopwatch stopwatch = new Stopwatch();
fsw.Created += OnFileCreated;
fsw.Changed += OnFileChanged;
fsw.Disposed += OnDisposed;
void OnFileCreated(object sender, FileSystemEventArgs e)
{
lock (locker)
{
fileName = e.Name;
stopwatch.Restart();
}
}
void OnFileChanged(object sender, FileSystemEventArgs e)
{
lock (locker)
{
if (e.Name == fileName && stopwatch.ElapsedMilliseconds < TOLERANCE_MSEC)
{
return; // Ignore this event
}
}
handler.Invoke(sender, e);
}
void OnDisposed(object sender, EventArgs e)
{
fsw.Created -= OnFileCreated;
fsw.Changed -= OnFileChanged;
fsw.Disposed -= OnDisposed;
}
}
用法示例:
var fsw = new FileSystemWatcher(DIR_NAME);
fsw.OnChangedByUser(File_ChangedByUser);
fsw.EnableRaisingEvents = true;
private static void File_ChangedByUser(object sender, FileSystemEventArgs e)
{
// Handle the event
}