xeondev

Dear all,

I've been reading through this forum for the issue that FSW will raise created event when the file copying begins and after some changed event is fired, but there is no event AFTER the file created.
The common solutions are:
1. Try to open and sleep if fails, try to open again. (I don't want to Thread.Sleep for other
reasons)
2. Start a timer on created event, reset on changed event when timer hit there is no more
changed events so we can consider it complete.

Not so perfect but could work, my concern is what if a process will "stuck" writing a file
(file1) and another process will do the correct work (file2). I suspect the FSW events will be similar like this:

created: file1
changed: file1
changed: file1
changed: file1
created: file2
changed: file1
changed: file2
changed: file1
.
.
.
changed: file1

It's a theory than i haven't simulated, but could it happen i suppose. What are you thinking And what could be the solution for getting to know that file2 acually created (there is no more changed event of course)

Many thanks
X


Re: .NET Base Class Library FileSystemWatcher created event fires too early (multitask)

Peter Ritchie

I'm not sure what you mean by "no event AFTER the file [is] created". Do you mean you're not getting modification notifications

Are you writing to a file in .NET code If you're using FileStream, the modification notifications won't propagate until FileStream.Close is called, even if you call FileStream.Flush. This has been logged here: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx FeedbackID=94772




Re: .NET Base Class Library FileSystemWatcher created event fires too early (multitask)

xeondev

Sorry Peter my post was a bit confusing, but i try again.
I have a simple console app.

class Program
{
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = @"c:\source";
watcher.Filter = "*.*";
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
watcher.IncludeSubdirectories = false;

watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Changed += new FileSystemEventHandler(watcher_Changed);

watcher.EnableRaisingEvents = true;

Console.WriteLine("Listening started");
Console.ReadLine();
}

static void watcher_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("Changed {0}", e.FullPath);
}

static void watcher_Created(object sender, FileSystemEventArgs e)
{
Console.WriteLine("Created {0}", e.FullPath);
}
}

If i drop some files in the source folder the result will be similar like this:
Listening started
Created c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Created c:\source\irany.JPG
Changed c:\source\irany.JPG
Changed c:\source\irany.JPG
Changed c:\source\irany.JPG
Created c:\source\krtipus.JPG
Changed c:\source\krtipus.JPG
Changed c:\source\krtipus.JPG
Changed c:\source\krtipus.JPG

I suppose if a slow process is generating "nyomt.JPG" and the other processes are faster
i could end up in the following result

Listening started
Created c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Created c:\source\irany.JPG
Changed c:\source\irany.JPG
Created c:\source\krtipus.JPG
Changed c:\source\krtipus.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG
Changed c:\source\nyomt.JPG

My real goal is to get to know when the creating is finished. The created event fires when the
creation is started. Other thread was also discussing this:
http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=603441&SiteID=1

scottwis_MS said:
"I would recommend that you use a timer component in conjunction with the FileSystemWatcher component, setting the time to something around 1 second or so. When you receive the "created" event you can then start the timer and then start listing to "changed" events from the FileSystemWatcher. Every time you get a changed event you can then reset the timer. Once the timer fires, you can then go ahead and do your processing."

I suppose a simple timer is not enough in the second "mixed" scenario, it needs somehow to track the events and filenames but i'm running out of ideas.

Regards
xeondev




Re: .NET Base Class Library FileSystemWatcher created event fires too early (multitask)

Peter Ritchie

Short answer is: you can't. Longer answer is: you can't do it reliably or transparently. "Created is finished" is subjective, it depends on the implementation of a particular application. One application the process of "creation" could be to open the file, write a byte, close the file, open the file, write a bunch of other bytes, then close the file. Another application can never know the applications invariant of a "valid file".

As Scott points out, one way to attempt to do what you want is to sit and watch Create/Changed events for a particular file and using a timer to tell if the file hasn't changed for a specifc amount of time and assume that means the creation is complete. The flaw with this is that no matter what time you use it won't be correct. The higher the value the less likely it will be that you interrupt the creation process; but you introduce a race condition and will eventually show up as a read or write issue (e.g. you've assumed the creation was complete and you've opened the file for read and denied exclusive access by the other application--resulting in an access violation).




Re: .NET Base Class Library FileSystemWatcher created event fires too early (multitask)

xeondev

Actually i have tried with a local copy from d: to c: , the file size is around 700M. The system raises the following events, so i doubt Scott's solution will work. I'd prefer to try opening the file in a timer event, if it succeeds i will consider it complete, if not propably is in progress of copy.

Created c:\source\AFulke.avi
2006.12.11. 8:59:21:450

Changed c:\source\AFulke.avi
2006.12.11. 8:59:21:520

Changed c:\source\AFulke.avi
2006.12.11. 8:59:21:520

Changed c:\source\AFulke.avi
2006.12.11. 8:59:52:184