c# - 带有 FileSystemWatcher 和 Timer 的 Windows 服务 - 确保所有内容都得到处理

标签 c# .net windows-services timer

我创建了一个 C# Windows 服务应用程序,该应用程序启动 FileSystemWatcher 来监视目录中文件的创建。找到文件后,我实例化一个自定义类,该类解析文件 (CSV) 并使用其内容调用 Web 服务。该服务在某种程度上是异步的,并返回一个唯一的编号,必须使用该编号进行后续调用以检查其进度。在我的流程类中,我创建了一个计时器来不断检查作业是否完成。当我完成后,我正在处置关闭我的计时器,但我只是想确保我的类将被垃圾收集,并且不会有任何内存泄漏.

代码如下所示(为简洁起见,进行了删减):

我的主要服务类别:

    protected override void OnStart(string[] args)
    {
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = "path";
        watcher.Filter = "file";
        watcher.Created += new FileSystemEventHandler(watcher_Created);
        watcher.EnableRaisingEvents = true;
    }

    static void watcher_Created(object sender, FileSystemEventArgs e)
    {
        FileProcessor p = new FileProcessor();
        p.Process(e.FullPath);

        //Will this instance of p stick around until the timer within it is finished?
    }

FileProcessor.cs

    class FileProcessor
    {
        private System.Timers.Timer timer = new System.Timers.Timer();
        private string id;

        public FileProcessor()
        {
            timer.Elapsed += new ElapsedEventHandler(OnTimer);
            timer.Enabled = false;
            timer.AutoReset = true;
        }

        public void Process(string filename)
        {
            //Read file <snipped>

            //Call web service and get id
            id = CallWebService();

            //Create a timer for 10 seconds and start it
            timer.Interval = 10000;
            timer.Enabled = true;
        }


        private bool IsFinished(string id)
        {
            //Call web service to see if job is finished, true if finished
            //<snipped>
        }


        private void ProcessResults()
        {
            //Job is finished, process results

            //Call cleanup method to dispose of timer
            Cleanup();
        }

        private void OnTimer(object source, ElapsedEventArgs e)
        {
            if (!IsFinished(id))
            {
                //Keep timer running, check result again next timer event
                return;
            }
            else
            {
                //Stop timer
                timer.Stop();

                //Process Results
                ProcessResults(response);
            }
        }


        private void Cleanup()
        {
            timer.Close();
            timer.Dispose();
        }
    }

我的问题是我的“p”实例应该保留(而不是被GC)直到我的计时器被销毁吗?它会被摧毁吗?我的 FileProcessor 类是否需要实现 IDisposable 以便我可以将其包装在 using block 中?我并不担心这是单线程的,因为我只希望它每天处理一个文件,并且该过程完成并返回以监视要创建的下一个文件的时间不应超过 10 分钟。

最佳答案

您走在正确的道路上。 FileSystemWatcher实现Component类,这要求您在使用后将其丢弃。既然是这种情况,正确的方法是让您的 FileProcessor 类按照您的建议实现 IDisposable。

由于FileProcessor对象将长期存在,因此您将无法使用 using陈述。这是因为该对象会在完成其工作之前尝试将其释放。

在这种情况下,我将在 FileProcessor 上实现一个事件,以在处理完成时通知使用者。完成后,我将调用 FileProcessor 对象上的 Dispose 方法。 Dispose 方法应该执行该对象所需的所有清理 - IE:计时器、观察器等。

供您引用,this is a good article其中列出了何时以及如何使用 IDisposable 接口(interface)的一些准则。另外,作为一个好的实践,您需要将消费者中的调用包装在 try/catch block 中 - 您需要确保无论发生什么情况,您都会尝试释放资源。

关于c# - 带有 FileSystemWatcher 和 Timer 的 Windows 服务 - 确保所有内容都得到处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7740421/

相关文章:

c# - 预定义类型 System.Object 未定义或导入

c# - 如何将 XmlElementAttribute 用于 List<T>?

c# - 在 C# 正则表达式中使用条件替换进行 CSS 缩小

windows - 从非交互式进程(Windows 服务、计划任务等)在 WinServer 2008 中打印 PDF

multithreading - Windows服务作为分层体系结构中的服务层

c# - 如何使用 LINQ 更新数据库? Linq-to-SQL

c# - 将每日事件时间转换为 "Mon-Fri 10:00-10:30AM"格式

c# - WPF 应用程序中的多个数据网格,但一次只显示一个

c# - .NET 的并发收集超时?

c# - 事件查看器 — 记录到子文件夹?