satyajit
satyajit

Reputation: 1570

How to force FileSystemWatcher to wait till the file downloaded?

I am downloading a file and want to execute the install only after the download is complete. How do I accomplish this? Seems like FileSystemWatcher onCreate event would do this but this happens in a different thread, is there a simple way to force the waiting part to happen in the same thread.

Code I have so far

 FileSystemWatcher w = new FileSystemWatcher(@"C:/downloads");
 w.EnableRaisingEvents = true;
 w.Created += new FileSystemEventHandler(FileDownloaded);

 static void FileDownloaded(object source, FileSystemEventArgs e)
 {
    InstallMSI(e.FullPath);
 }

I looked at SynchronizingObject and WaitForChangedResult but didn't get a solid working sample.

Upvotes: 12

Views: 15154

Answers (4)

Simen S
Simen S

Reputation: 3205

If you insist on using FileSystemWatcher you would probably have to account for the fact that a file of some size isn't created (uploaded) in one single operation. The filesystem is likely to produce 1 created and x changed events before the file is ready for use.

You could catch the created events and create new (dedicated) threads (unless you already have an ongoing thread for that file) in which you loop and periodically try to open the file exclusively. If you succeed, the file is ready.

Upvotes: 5

ukhardy
ukhardy

Reputation: 2104

Try:

FileInfo fInfo = new FileInfo(e.FullPath); 
while(IsFileLocked(fInfo)){
     Thread.Sleep(500);     
}
InstallMSI(e.FullPath);


static bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;
    try {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException) {
        return true;
    }
    finally {
        if (stream != null)
            stream.Close();
    }   
    return false;
}

Upvotes: 17

Marcus
Marcus

Reputation: 5447

If you are using WebClient to download, you can use set the client's DownloadFileCompleted eventhandler.
If you do it this way you can also use client.DownloadFileAsync() to make it download asynchronously.

Upvotes: 2

Chris Wenham
Chris Wenham

Reputation: 24017

One technique would be to download to the temporary directory, and then move it into C:/downloads once it was complete.

Upvotes: 2

Related Questions