tags:

views:

173

answers:

4

I'm copying from a client computer to a server computer in a shared directory. My server detects the new file, and after the copying is complete it has to process it. The problem is that, when writing a big file and using FileSystemWatcher, you get no indication whether the copying is done or not. The only way to check this is by trying to open the file (File.OpenRead/OpenWrite) and getting an exception. How can I get a notification that the copy is complete without resorting to exception handling as flow control?

My first thought is if I could detect when the handle used for writing to the file is closed, I could tell exactly when the copying is complete, but I'm not sure how to do that.

+1  A: 

Instead of using this ad-hoc notification of polling FileSystemWatcher, why can't the client explicitly notify the server via a WCF service call (or whatever)? You could even make a simple EXE that the client has called NotifyServerFileUploaded.exe [name of file].

This way, there's no polling, no handle trickery, and no perf problems.

Paul Betts
What if on the client he's using Windows Explorer to simply drag a file to a network share?
280Z28
A: 

Copy the file to a temp file. When the copy is complete, rename. Renaming is atomic. Just make sure the server computer ignores the temp files.

Joel Rondeau
A: 

retry the file for exclusive read.

int maxRetry = 3;
int x = 0;
tryAgain:
try
{
    using (var fs = File.Open("file.txt", FileMode.Open, 
                                          FileAccess.Read, 
                                          FileShare.None))
    {
        // you have exclusive read here
    }
}
catch (IOException)
{
    if (x++ > maxRetry)
        throw;
    Thread.Sleep(500);
    goto tryAgain;
}
Matthew Whited
yes... if you have a phobia of goto you can use a while or a for.
Matthew Whited
(I think IOException is what is thrown when you don't have exclusive access... you may either need to use a different exception or just catch Exception... that's up to you)
Matthew Whited
yeah well, that's what i had in mind. That's what i suggested in the subject. But i know that throwing/catching exceptions, acts defavorably on the application (heavily), and i don't want my application to keep on catching exceptions.I'm searching for another way around it.
LolaRun
Put this in the handler for a file watcher. You may be able to find something with platform invoke... but I'm not sure.
Matthew Whited
A: 

Have you tried using FilesystemWatcher and the Created event?

myWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Security | NotifyFilters.DirectoryName;


myWatcher.Created += new FileSystemEventHandler(watcher_Changed);
Tom Newman