如何强制FileSystemWatcher等到文件下载?

时间:2011-03-08 20:25:17

标签: c# multithreading filesystemwatcher

我正在下载文件,并希望在下载完成后才执行安装。我该如何做到这一点?好像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 个答案:

答案 0 :(得分:14)

尝试:

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;
}

答案 1 :(得分:5)

如果您坚持使用FileSystemWatcher,则可能需要考虑到在单个操作中未创建(上载)某个大小的文件的事实。在文件准备好使用之前,文件系统可能会产生1 created和x changed个事件。

您可以捕获created个事件并创建新的(专用)线程(除非您已经拥有该文件的持续线程),您可以在其中循环并定期尝试以独占方式打开该文件。如果成功,文件就准备好了。

答案 2 :(得分:2)

一种技术是下载到临时目录,然后将其移动到C:/ downloads中。

答案 3 :(得分:2)

如果您使用WebClient进行下载,则可以使用设置客户端的DownloadFileCompleted事件处理程序。
如果你这样做,你也可以使用client.DownloadFileAsync()进行异步下载。