在 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 类对数组进行洗牌 [重复]

如何在c#中对所有日志进行分组

什么时候在 C# 中返回空引用类型是正确的 [重复]

C# - 计时器滴答时间比指定的间隔更短,导致重复作业并行运行

C# LINQ 组按属性集合,然后按列表定义的显式顺序对每个组进行排序[重复]