Как заставить FileSystemWatcher ждать, пока файл загрузится? - PullRequest
8 голосов
/ 08 марта 2011

Я загружаю файл и хочу выполнить установку только после завершения загрузки. Как мне это сделать? Похоже, событие FileSystemWatcher onCreate будет делать это, но это происходит в другом потоке, есть простой способ заставить ожидающую часть происходить в том же потоке.

Код, который у меня есть до сих пор

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

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

Я посмотрел на SynchronizingObject и WaitForChangedResult, но не получил надежный рабочий образец.

Ответы [ 4 ]

14 голосов
/ 08 марта 2011

Попробуйте:

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;
}
5 голосов
/ 08 марта 2011

Если вы настаиваете на использовании FileSystemWatcher, вам, вероятно, придется учитывать тот факт, что файл некоторого размера не создается (загружается) за одну операцию. Файловая система может генерировать события 1 created и x changed до того, как файл будет готов к использованию.

Вы можете перехватить события created и создать новые (выделенные) потоки (если у вас уже нет текущего потока для этого файла), в котором вы зацикливаетесь и периодически пытаетесь открыть файл исключительно. Если вам это удастся, файл готов.

2 голосов
/ 08 марта 2011

Если вы используете WebClient для загрузки, вы можете установить клиентский обработчик событий DownloadFileCompleted. Если вы делаете это таким образом, вы также можете использовать client.DownloadFileAsync() для асинхронной загрузки.

2 голосов
/ 08 марта 2011

Один из методов заключается в том, чтобы загрузить во временный каталог, а затем переместить в C: / downloads после его завершения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...