问题
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 dispose
ing and close
ing 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
//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();
}
}
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.
回答1:
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.
来源:https://stackoverflow.com/questions/7740421/windows-service-with-filesystemwatcher-and-timer-making-sure-everything-gets-d