2

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.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
LolaRun
  • 5,526
  • 6
  • 33
  • 45

4 Answers4

1

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.

Ana Betts
  • 73,868
  • 16
  • 141
  • 209
1

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
  • 7,486
  • 2
  • 42
  • 54
1

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
  • 11
  • 1
0

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
  • 22,160
  • 4
  • 52
  • 69
  • yes... if you have a phobia of goto you can use a while or a for. – Matthew Whited Feb 23 '10 at 19:09
  • (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 Feb 23 '10 at 19:11
  • 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 Mar 01 '10 at 16:12
  • 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 Mar 01 '10 at 17:56