gpt4 book ai didi

c# - FileSystemWatcher 多次触发事件的强大解决方案

转载 作者:行者123 更新时间:2023-12-05 03:07:27 25 4
gpt4 key购买 nike

FileSystemWatcher 事件可以触发多次。如果我的代码需要可预测的行为,那就不好了。

这在 MSDN documentation 中有描述:

Common file system operations might raise more than one event. For example, when a file is moved from one directory to another, several OnChanged and some OnCreated and OnDeleted events might be raised. Moving a file is a complex operation that consists of multiple simple operations, therefore raising multiple events. Likewise, some applications (for example, antivirus software) might cause additional file system events that are detected by FileSystemWatcher.

对特定事件充分使用 NotifyFilters 有所帮助,但不会让我对一致性有 100% 的信心。

这是一个示例,重新创建记事本写入示例(但我在其他写入操作中也遇到过这种情况):

 public ExampleAttributesChangedFiringTwice(string demoFolderPath)
{
var watcher = new FileSystemWatcher()
{
Path = @"c:\temp",
NotifyFilter = NotifyFilters.LastWrite,
Filter = "*.txt"
};

watcher.Changed += OnChanged;
watcher.EnableRaisingEvents = true;
}

private static void OnChanged(object source, FileSystemEventArgs e)
{
// This will fire twice if I edit a file in Notepad
}

有什么建议可以让它更有弹性吗?

编辑:意思是在触发多个事件时不重复多个操作。

最佳答案

一种利用 MemoryCache 作为缓冲区来“限制”额外事件的方法。

  1. 触发文件事件(在本例中为Changed)
  2. 事件由 OnChanged 处理,但它没有完成所需的操作,而是将事件存储在 MemoryCache 中 1秒过期 和一个在到期时执行的 CacheItemPolicy 回调设置。

请注意,我使用 AddOrGetExisting 作为一种简单的方法来阻止在缓存期间触发的任何其他事件被添加到缓存中。

  1. 当它过期时,回调 OnRemovedFromCache 完成针对该文件事件的行为

.

  class BlockAndDelayExample
{
private readonly MemoryCache _memCache;
private readonly CacheItemPolicy _cacheItemPolicy;
private const int CacheTimeMilliseconds = 1000;

public BlockAndDelayExample(string demoFolderPath)
{
_memCache = MemoryCache.Default;

var watcher = new FileSystemWatcher()
{
Path = demoFolderPath,
NotifyFilter = NotifyFilters.LastWrite,
Filter = "*.txt"
};

_cacheItemPolicy = new CacheItemPolicy()
{
RemovedCallback = OnRemovedFromCache
};

watcher.Changed += OnChanged;
watcher.EnableRaisingEvents = true;
}

// Add file event to cache for CacheTimeMilliseconds
private void OnChanged(object source, FileSystemEventArgs e)
{
_cacheItemPolicy.AbsoluteExpiration =
DateTimeOffset.Now.AddMilliseconds(CacheTimeMilliseconds);

// Only add if it is not there already (swallow others)
_memCache.AddOrGetExisting(e.Name, e, _cacheItemPolicy);
}

// Handle cache item expiring
private void OnRemovedFromCache(CacheEntryRemovedArguments args)
{
if (args.RemovedReason != CacheEntryRemovedReason.Expired) return;

// Now actually handle file event
var e = (FileSystemEventArgs) args.CacheItem.Value;
}
}

可以很容易地扩展到:

  • 检查缓存中过期的文件锁,如果不可用,将其再次放回缓存中(有时事件触发得太快,文件还没有准备好进行某些操作)。最好使用 try/catch 循环。
  • 文件名+事件类型组合的键缓存

关于c# - FileSystemWatcher 多次触发事件的强大解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47273578/

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