2011-03-08 17 views
7

Estoy descargando un archivo y quiero ejecutar la instalación solo después de que se complete la descarga. ¿Cómo logro esto? Parece que el evento FileSystemWatcher onCreate haría esto, pero esto sucede en un hilo diferente, ¿hay una manera simple de forzar a la parte de espera a suceder en el mismo hilo?¿Cómo forzar a FileSystemWatcher a esperar hasta que se descargue el archivo?

código que tengo hasta ahora

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

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

me miraba SynchronizingObject y WaitForChangedResult pero no obtuvo una muestra de trabajo sólida.

+0

¿Cómo está descargando el archivo? El código de muestra es bueno. – unholysampler

+0

la descarga se realiza en la interfaz de usuario ... ese código hará que esta pregunta sea complicada. Solo puedo decir que para cuando se active este código, la acción de descarga ya ha comenzado – satyajit

+0

posible duplicado de [FileSystemWatcher Work Done?] (Http://stackoverflow.com/questions/4662893/filesystemwatcher-work-is-done) –

Respuesta

2

Una técnica sería descargar en el directorio temporal, y luego mover en C:/descargas una vez que se haya completado.

+0

¿Cómo sabría si la descarga está completa, es decir, cuándo se debe activar el movimiento? – satyajit

+0

Depende de cómo lo está descargando. ¿Cómo se ve el código? –

+2

Haz x cuando se complete la descarga. Bueno, esa es la pregunta! – ukhardy

2

Si está utilizando WebClient para descargar, puede usar configurar el controlador de eventos DownloadFileCompleted del cliente.
Si lo hace de esta manera, también puede usar client.DownloadFileAsync() para que se descargue de forma asíncrona.

14

Probar:

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

Esta es la solución más directa, pero no quiero usar más thread.sleeps en mi código. Así que estoy usando el otro enfoque – satyajit

+0

Estoy escribiendo una aplicación de consola y esto funcionó perfectamente. Como solo tengo un hilo, estoy usando esto. +1. – JohnP

+0

¿Quizás agregue un cheque para si el archivo existe? –

5

Si usted insiste en el uso de FileSystemWatcher que probablemente habría que tener en cuenta el hecho de que un archivo de un cierto tamaño no se crea (cargado) en una sola operación. Es probable que el sistema de archivos produzca eventos 1 created y x changed antes de que el archivo esté listo para su uso.

Puede ver los eventos created y crear hilos nuevos (dedicados) (a menos que ya tenga un hilo en curso para ese archivo) en los que itera y periódicamente intenta abrir el archivo exclusivamente. Si tiene éxito, el archivo está listo.

+0

Esto es absolutamente cierto. He estado usando esto para un programa simple de transferencia sFTP, e incluso un archivo de 17k copiado del directorio raíz al directorio de prueba produjo 1 creado y 4 eventos modificados. – JohnP

Cuestiones relacionadas