Windows Service File Listener

V

Vinny

Hey all. I'm now attributing the problem I'm having to something
incredibly simple, to which I must be overlooking.

I created a Windows Service application that listens for files. The
file paths are in a config file. I then write information out to an
event log so as files are dropped into their location, I receive
information. Lastly, I wish to delete the file(s) once they are dropped
.. This is where I'm getting the awkward behavior. I get the following
exception (sometimes):

"The process cannot access the file "C:\temp\test1.txt" because it is
being used by another process."
The sometimes occurence tells me that I am either having a garbage
collection or threading problem. Here is the code I use to add the file
listener for each file:

foreach(XmlNode XNode in Config.DocumentElement.SelectNodes("folder"))
{
fileSystemWatcher = new System.IO.FileSystemWatcher();

((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher)).BeginInit();
fileSystemWatcher.Path =
Path.GetDirectoryName(XNode.Attributes["name"].Value.ToString());
fileSystemWatcher.Filter =
Path.GetFileName(XNode.Attributes["name"].Value.ToString());
this.fileSystemWatcher.EnableRaisingEvents = true;
this.fileSystemWatcher.Created += new
System.IO.FileSystemEventHandler(this.fileSystemWatcher_Created);

((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher)).EndInit();
eventLog1.WriteEntry("Adding File Watcher for " +
XNode.Attributes["name"].Value.ToString());
}

this code does work correctly, as the Created event does fire anytime I
add one of the files specified in the app.config file to the directory.

This is the Created event code:

private void fileSystemWatcher_Created(object sender,
System.IO.FileSystemEventArgs e)
{
eventLog1.WriteEntry(e.FullPath.ToString() + " has been delivered");
try
{
File.Delete(e.FullPath);
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
I got desperate and tried to invoke some garbage collection, but the
behavior did not change:

byte[] bytes = new byte[100*(1<<20)];
for(int i=0; i<bytes.Length; i++)
bytes = 0;
bytes = null;
GC.Collect();
Thread.Sleep(2000);

Anyone out there with any ideas, I'd really appeciate it. Thanks
all!!!!
 
J

Jon Skeet [C# MVP]

Vinny said:
Hey all. I'm now attributing the problem I'm having to something
incredibly simple, to which I must be overlooking.

I created a Windows Service application that listens for files. The
file paths are in a config file. I then write information out to an
event log so as files are dropped into their location, I receive
information. Lastly, I wish to delete the file(s) once they are dropped
. This is where I'm getting the awkward behavior. I get the following
exception (sometimes):

<snip>

The problem is just that you're getting told when the file is being
created, not when whatever's creating it has finished writing to it.

You could loop round for a few times, sleeping between attempts, until
you can delete it.
 
V

Vinny

Thanks for the quick response. It turns out that the Changed event as
opposed to the Created event provides the consistency I was looking
for. Also, adding a short duration sleep command (100 ms) allowed the
service (which is multi-threaded) to relinquish control to the worker
threads. Unfortunately, using the Changed event , triggers multiple
times as the file is being written to the directory, which results in
multiple writes to the event log for a single file. Is there any way to
check when a file has completed writing after being placed in a folder?
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

No really, you can do one of several things:
1- If you control the file's generator you can opt to create a "flag" file
with the same name that the output file with a different extension, and
"watch" this flag file instead of the content file itself.
2- use a timespan and ignore the events that occur before the timespan
elapse, this would prevent to process two close events.


Or a combination of both.


Cheers,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top