开发者

Windows service with FileSystemWatcher and Timer - making sure everything gets disposed

开发者 https://www.devze.com 2023-04-12 06:45 出处:网络
I have created a C# Windows Service application that starts a FileSystemWatcher to monitor a directory for the creation of a file.When the file is found I instantiate a custom class that parses the fi

I have created a C# Windows Service application that starts a FileSystemWatcher to monitor a directory for the creation of a file. When the file is found I instantiate a custom class that parses the file (CSV) and calls a web service with it's contents. The service is somewhat asynchronous and returns a unique number which must be used for subsequent calls to check its progress. In my process class I create a timer to continually check to see if the job is finished. I am disposeing and closeing my timer when I am done with it but I just want to make sure my class will be garbage collected and I will not have any memory leaks.

The code looks like this (snipped for brevity):

My main service class:

    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

            //Cal开发者_高级运维l 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();
        }
    }

My question is should my instance of "p" stick around (not be GC'ed) until my timer is destroyed? Will it ever be destroyed? Does my FileProcessor class need to implement IDisposable so I can wrap it in a using block? I am not worried about this being single threaded because I only expect it to process one file per day and it should not take more than 10 minutes for the process to finish and return to watching for the next file to be created.


You are on the right track. FileSystemWatcher implements the Component class, which requires you to dispose it after use. Since this is the case, the correct approach would be to have your FileProcessor class implement IDisposable as you suggested.

Since you are going to have the FileProcessor object live for an extended period of time, you will not be able to use a using statement. This is because the object would attempt to get disposed before it was done with its work.

This being the case, I would implement an event on the FileProcessor to notify the consumer when processing is complete. When this is complete I would call the Dispose method on the FileProcessor object. The Dispose method should perform all cleanup required for that object - IE: timer, watcher, etc.

For your reference, this is a good article which lays out some guidelines for when and how to use the IDisposable interface. Also, as a good practice, you will want to wrap the calls in the consumer in try/catch blocks - you need to ensure that no matter what happens, you attempt to free the resources.

0

精彩评论

暂无评论...
验证码 换一张
取 消