在 C# 中使用计时器重复对每个目录进行方法调用
Posted
技术标签:
【中文标题】在 C# 中使用计时器重复对每个目录进行方法调用【英文标题】:Repeating a method call on each direcotry with timer elasped in C# 【发布时间】:2019-04-20 06:33:43 【问题描述】:概述:
我创建了两个FileSystemWatcher
来检测子文件夹及其文件的创建。我还对第二个观察者(文件观察者)使用了Timer
,它会在动态调用 zip 方法之前为每个文件夹中创建的每个文件重新启动计时器。
我尝试对每个文件夹执行此过程,但无论是否有文件移动到这些文件夹中,它都会一次压缩所有文件夹。
下面是我模拟计时器和 zip 过程的代码的一部分...在调用 zip 方法时,将 zip 文件移动到根文件夹时可能会遇到问题。
文件Watcher中的定时器
namespace ZipperAndWatcher
public class Archive
public void CreateZip(string path)
// zip method code
public class FileWatcher
private FileSystemWatcher _fsw;
private Archive _zip;
private string _path;
private Timer _timer;
public FileWatcher()
_fsw = new FileSystemWatcher();
_zip = new Archive();
_path = @"D:\Documents\output";
_timer = new Timer();
public void StartWatching()
var rootWatcher = _fsw;
rootWatcher.Path = _path;
rootWatcher.Created += new FileSystemEventHandler(OnRootFolderCreated);
rootWatcher.EnableRaisingEvents = true;
rootWatcher.Filter = "*.*";
private void OnRootFolderCreated(object sender, FileSystemEventArgs e)
string watchedPath = e.FullPath; // watched path
// create another watcher for file creation and send event to timer
FileSystemWatcher subFolderWatcher = new FileSystemWatcher();
subFolderWatcher.Path = watchedPath + @"\";
// Timer setting
var aTimer = _timer;
aTimer.Interval = 20000;
// Lambda == args => expression
// send event to subFolderWatcher
aTimer.Elapsed += new ElapsedEventHandler((subfolderSender, evt) => OnTimedEvent(subfolderSender, evt, subFolderWatcher));
aTimer.AutoReset = false;
aTimer.Enabled = true;
// sub-folder sends event to timer (and wait timer to notify subfolder)
subFolderWatcher.Created += new FileSystemEventHandler((s, evt) => subFolderWatcher_Created(s, evt, aTimer));
subFolderWatcher.Filter = "*.*";
subFolderWatcher.EnableRaisingEvents = true;
private void OnTimedEvent(object sender, ElapsedEventArgs evt, FileSystemWatcher subFolderWatcher)
subFolderWatcher.EnableRaisingEvents = false;
// Explicit Casting
Timer timer = sender as Timer;
timer.Stop();
timer.Dispose();
// Once time elapsed, zip the folder here?
Console.WriteLine($"time up. zip process at evt.SignalTime");
Archive zip = _zip;
zip.CreateZip(subFolderWatcher.Path.Substring(0, subFolderWatcher.Path.LastIndexOf(@"\")));
subFolderWatcher.Dispose();
private void subFolderWatcher_Created(object sender, FileSystemEventArgs evt, Timer aTimer)
// if new file created, stop the timer
// then restart the timer
aTimer.AutoReset = false;
aTimer.Stop();
aTimer.Start();
Console.WriteLine($"restart the timer as evt.Name created on DateTime.Now.ToString()");
【问题讨论】:
如何设置文件系统观察者及其定时器?我想知道事件处理程序如何获取它们的额外参数。 我在根文件夹的 OnCreated 事件处理程序中设置了第二个观察者和计时器,并使用上面的代码进行了扩展,第二个观察者将事件发送到计时器,并且计时器将事件发送到第二个观察者在一定程度上相互交互。我不确定如何分别对每个文件夹进行 zip 处理。 能否将此代码添加到问题中? @KlausGütter 我的代码可能又长又丑,但你可以找到它here。我的道歉。 坦率地说,我不明白你的问题。是不是您的 CreateZip 方法总是压缩所有子目录,而不仅仅是添加了新文件的子目录?如果您不希望这样做,只需将正确目录的路径传递给方法并从 CreateZip 中删除子目录上的 foreach 循环。 【参考方案1】:您在上一条评论中写道:“我想要的是仅压缩特定的子目录,经过一段时间后不再添加文件,而其他子目录可能仍有文件添加,并且还没有准备好压缩”
因此,在您的计时器处理程序 (OnTimedEvent) 中,您需要将路径传递到准备压缩到 CreateZip 的目录,而不是父目录,即更改
zip.CreateZip(subFolderWatcher.Path.Substring(0, subFolderWatcher.Path.LastIndexOf(@"\")));
到
zip.CreateZip(subFolderWatcher.Path);
然后在您的 CreateZip 方法中,只需压缩作为参数传递的目录,而不是像现在这样压缩所有子目录。
【讨论】:
谢谢,这行得通,但是如果我希望每个子目录在不同的时间压缩自己,不知道我应该删除 zip 方法中的foreach
吗?
如果我正确理解了您的代码,您的每个子目录都有一个计时器,因此它们已经独立运行。
是的,这正是计时器所做的,但我希望每个子目录都应该压缩自己一次 (1) 时间已过,并且 (2) 在该子目录中不再添加文件。我仍然无法做到这一点。
当有新文件到达时,您不是已经重新启动计时器了吗?这应该处理 (1) 和 (2)。以上是关于在 C# 中使用计时器重复对每个目录进行方法调用的主要内容,如果未能解决你的问题,请参考以下文章
C# - Span 全面介绍:探索 .NET 新增的重要组成部分
如何在 C# 中使用 Random 类对数组进行洗牌 [重复]