use*_*707 316 c# filesystemwatcher
我有一个应用程序,我正在寻找一个文本文件,如果对文件进行任何更改,我使用OnChanged
eventhandler来处理事件.我正在使用NotifyFilters.LastWriteTime
但事件仍被解雇两次.这是代码.
public void Initialize()
{
FileSystemWatcher _fileWatcher = new FileSystemWatcher();
_fileWatcher.Path = "C:\\Folder";
_fileWatcher.NotifyFilter = NotifyFilters.LastWrite;
_fileWatcher.Filter = "Version.txt";
_fileWatcher.Changed += new FileSystemEventHandler(OnChanged);
_fileWatcher.EnableRaisingEvents = true;
}
private void OnChanged(object source, FileSystemEventArgs e)
{
.......
}
Run Code Online (Sandbox Code Playgroud)
在我的情况下OnChanged
,当我更改文本文件version.txt
并保存时,会调用两次.
Jør*_*ode 270
我担心这是该FileSystemWatcher
课程中众所周知的错误/特征.这来自该课程的文档:
在某些情况下,您可能会注意到单个创建事件会生成由组件处理的多个Created事件.例如,如果使用FileSystemWatcher组件来监视目录中新文件的创建,然后使用记事本创建文件进行测试,即使只创建了一个文件,也可能会看到生成两个Created事件.这是因为Notepad在写入过程中执行多个文件系统操作.记事本批量写入磁盘,创建文件的内容,然后创建文件属性.其他应用程序可以以相同的方式执行.由于FileSystemWatcher监视操作系统活动,因此将拾取这些应用程序触发的所有事件.
现在这段文本是关于Created
事件的,但同样的事情也适用于其他文件事件.在某些应用程序中,您可以通过使用该NotifyFilter
属性来解决这个问题,但我的经验表明,有时您还必须进行一些手动重复过滤(hacks).
前一段时间我预订了一个带有一些FileSystemWatcher提示的页面.你可能想看一下.
Dav*_*ant 145
我在我的委托中使用以下策略"修复"了这个问题:
// fsw_ is the FileSystemWatcher instance used by my application.
private void OnDirectoryChanged(...)
{
try
{
fsw_.EnableRaisingEvents = false;
/* do my stuff once asynchronously */
}
finally
{
fsw_.EnableRaisingEvents = true;
}
}
Run Code Online (Sandbox Code Playgroud)
BaB*_*aBu 103
通过检查相关文件的时间戳,可以检测并丢弃OnChanged
来自的任何重复事件.像这样:FileSystemWatcher
File.GetLastWriteTime
DateTime lastRead = DateTime.MinValue;
void OnChanged(object source, FileSystemEventArgs a)
{
DateTime lastWriteTime = File.GetLastWriteTime(uri);
if (lastWriteTime != lastRead)
{
doStuff();
lastRead = lastWriteTime;
}
// else discard the (duplicated) OnChanged event
}
Run Code Online (Sandbox Code Playgroud)
Dee*_*hri 21
这是我的解决方案,帮助我阻止事件被提升两次:
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
Run Code Online (Sandbox Code Playgroud)
这里我设置的NotifyFilter
属性只有Filename和size.
watcher
是FileSystemWatcher的对象.希望这会有所帮助.
我创建了一个带有类的 Git 存储库,该类扩展FileSystemWatcher
为仅在复制完成时触发事件。它丢弃除最后一个之外的所有更改事件,并且仅当文件可供读取时才引发它。
下载FileSystemSafeWatcher并将其添加到您的项目中。
然后将其用作正常FileSystemWatcher
事件并在事件触发时进行监控。
var fsw = new FileSystemSafeWatcher(file);
fsw.EnableRaisingEvents = true;
// Add event handlers here
fsw.Created += fsw_Created;
Run Code Online (Sandbox Code Playgroud)
这是我的方法:
// Consider having a List<String> named _changedFiles
private void OnChanged(object source, FileSystemEventArgs e)
{
lock (_changedFiles)
{
if (_changedFiles.Contains(e.FullPath))
{
return;
}
_changedFiles.Add(e.FullPath);
}
// do your stuff
System.Timers.Timer timer = new Timer(1000) { AutoReset = false };
timer.Elapsed += (timerElapsedSender, timerElapsedArgs) =>
{
lock (_changedFiles)
{
_changedFiles.Remove(e.FullPath);
}
};
timer.Start();
}
Run Code Online (Sandbox Code Playgroud)
这是我在一个项目中解决此问题的解决方案,我将该文件作为附件发送到邮件中.即使定时器间隔较小,它也可以轻松避免两次触发事件,但在我的情况下,1000是好的,因为我更幸福的是,错过了一些变化,而不是每秒输入> 1条消息.至少它可以正常工作,以防几个文件在同一时间更改.
我想到的另一个解决方案是用字典映射文件替换列表到它们各自的MD5,因此您不必选择任意间隔,因为您不必删除条目但更新其值,并且如果没有改变,取消你的东西.随着文件被监控并占用越来越多的内存,它有一个字典在内存中增长的缺点,但我已经读过某个地方,监控的文件数量取决于FSW的内部缓冲区,所以可能不那么重要.不知道MD5的计算时间如何影响你的代码的表现,小心=
小智 8
Try with this code:
class WatchPlotDirectory
{
bool let = false;
FileSystemWatcher watcher;
string path = "C:/Users/jamie/OneDrive/Pictures/Screenshots";
public WatchPlotDirectory()
{
watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "*.*";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
watcher.EnableRaisingEvents = true;
}
void OnChanged(object sender, FileSystemEventArgs e)
{
if (let==false) {
string mgs = string.Format("File {0} | {1}",
e.FullPath, e.ChangeType);
Console.WriteLine("onchange: " + mgs);
let = true;
}
else
{
let = false;
}
}
void OnRenamed(object sender, RenamedEventArgs e)
{
string log = string.Format("{0} | Renamed from {1}",
e.FullPath, e.OldName);
Console.WriteLine("onrenamed: " + log);
}
public void setPath(string path)
{
this.path = path;
}
}
Run Code Online (Sandbox Code Playgroud)
我的方案是我有一台带有Linux服务器的虚拟机.我正在Windows主机上开发文件.当我在主机上的文件夹中更改某些内容时,我希望上传所有更改,并通过Ftp同步到虚拟服务器上.这是我写入文件时删除重复更改事件的方法(标记包含要修改的文件的文件夹):
private Hashtable fileWriteTime = new Hashtable();
private void fsw_sync_Changed(object source, FileSystemEventArgs e)
{
string path = e.FullPath.ToString();
string currentLastWriteTime = File.GetLastWriteTime( e.FullPath ).ToString();
// if there is no path info stored yet
// or stored path has different time of write then the one now is inspected
if ( !fileWriteTime.ContainsKey(path) ||
fileWriteTime[path].ToString() != currentLastWriteTime
)
{
//then we do the main thing
log( "A CHANGE has occured with " + path );
//lastly we update the last write time in the hashtable
fileWriteTime[path] = currentLastWriteTime;
}
}
Run Code Online (Sandbox Code Playgroud)
主要是我创建一个哈希表来存储文件写入时间信息.然后,如果哈希表具有被修改的文件路径,并且它的时间值与当前通知的文件的更改相同,那么我知道它是事件的副本并忽略它.
我知道这是一个老问题,但有同样的问题,上述解决方案都没有真正解决我面临的问题。我创建了一个字典,用 LastWriteTime 映射文件名。因此,如果文件不在字典中,则继续执行该过程,否则请检查上次修改时间是什么时候,如果与字典中的不同,则运行代码。
Dictionary<string, DateTime> dateTimeDictionary = new Dictionary<string, DateTime>();
private void OnChanged(object source, FileSystemEventArgs e)
{
if (!dateTimeDictionary.ContainsKey(e.FullPath) || (dateTimeDictionary.ContainsKey(e.FullPath) && System.IO.File.GetLastWriteTime(e.FullPath) != dateTimeDictionary[e.FullPath]))
{
dateTimeDictionary[e.FullPath] = System.IO.File.GetLastWriteTime(e.FullPath);
//your code here
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
123018 次 |
最近记录: |