2012-08-01 12 views
6

mi sono bloccato con un problema strano (che è probabilmente la mia mancanza di conoscenza), vi presento il codice incriminato:funzioni Elimina Elimina anche quando si chiama applicazione è chiusa

try 
{ 
    f.Delete(); 
    fTemp.MoveTo(f.FullName); 
    Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName); 
} 
catch (IOException ex) 
{ 
    Console.WriteLine("ERROR: Output file has IO exception > {0}", f.FullName); 
    Environment.ExitCode = 1; 
} 

fe ftemp sono oggetti FileInfo. Quindi se eseguo questo con codice in cui f è un file video riprodotto in un mediaplayer lancia l'eccezione. Funziona bene e come previsto. Ora quando chiudo il mediaplayer cancella il file !? Anche se la mia domanda è chiusa da tempo. Anche quando chiudo Visual Studio, continua a eliminare il file quando chiudo il mediaplayer. Come se qualche callback venisse installato da qualche parte per assicurarsi che il file venisse cancellato ad un certo punto. Questo è un comportamento indesiderato. Ma io non riesco a capire che cosa va storto ... esattamente

Risultato per ora:

if (!IsFileLocked(f)) 
{ 
    try 
    { 
     f.Delete(); 
     fTemp.MoveTo(f.FullName); 
     Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName); 
    } 
    catch (IOException ex) 
    { 
     Console.WriteLine("ERROR: Output file has IO exception > {0}", f.FullName); 
     Environment.ExitCode = 1; 

    } 

    catch (UnauthorizedAccessException ex) 
    { 
     Environment.ExitCode = 2; 
     Console.WriteLine("ERROR: Output file is locked > {0}", f.FullName); 

    } 
} 
else 
{ 
    Environment.ExitCode = 3; 
    Console.WriteLine("ERROR: Couldn't delete file was locked"); 

} 

so che ancora posso fare meglio tra Elimina e MoveTo, ma mi prendo le mie modifiche per ora , codifica shotgun .....

+5

Il lettore multimediale molto probabilmente ha aperto il file con FILE_SHARE_DELETE, che significa "consenti alle persone di eliminare il file mentre lo sto usando". Il file è contrassegnato per la cancellazione e la cancellazione viene completata quando il lettore multimediale chiude il file. –

+2

Qual è il messaggio fornito con IOException? –

+0

Ma poi mi aspetterei che l'eccezione non venga sollevata. Inoltre l'ho aperto con Windows Media Player, che nel mio libro è infamemente file di blocco ... o non è lo stesso della bandiera che intendi. – JHN

risposta

3

Si sta ottenendo il IOException perché il file non può essere cancellato o scritto immediatamente. Tuttavia, quando si chiama Delete(), sembra che il file viene sempre chiamato per l'eliminazione.

Anche se il lettore multimediale si ferma il file venga eliminato mentre è aperto, il file è ancora contrassegnato per l'eliminazione quando si chiude, a prescindere dal fatto che il programma è in esecuzione. Quindi, quando il lettore multimediale si chiude, il file viene cancellato.

è possibile verificare se il file è in uso con il seguente codice, tratto da here. Rendere il Delete e Copy condizione che esso non essere bloccato, e si dovrebbe essere buono.

try 
{ 
    if(!IsFileLocked(f)) 
    { 
     f.Delete(); 
     fTemp.MoveTo(f.FullName); 
     Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName); 
    } 
} 

protected virtual bool IsFileLocked(FileInfo file) 
{ 
    FileStream stream = null; 

    try 
    { 
    stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
    } 
    catch (IOException) 
    { 
    //the file is unavailable because it is: 
    //still being written to 
    //or being processed by another thread 
    //or does not exist (has already been processed) 
    return true; 
    } 
    finally 
    { 
    if (stream != null) 
     stream.Close(); 
    } 

    //file is not locked 
    return false; 
} 
+0

Posso non "cancellare la bandiera" o qualsiasi machanisme era a posto. O meglio ancora, c'è un controllo che può essere fatto se il file può essere cancellato in primo luogo, questo comportamento è imprevedibile per me ora. – JHN

+0

Vedere la mia modifica sopra. –

+0

Vedo, mi ci è voluto troppo tempo per scrivere la mia risposta ... :) – Hinek

1

Da Windows SDK:

La funzione DeleteFile segna un file per l'eliminazione su una stretta. Di conseguenza, la cancellazione del file non si verifica finché non viene chiuso l'ultimo handle del file. Le chiamate successive a CreateFile per l'apertura del file non riescono con ERROR_ACCESS_DENIED.

0

Per quanto ho capito, volete che il vostro programma per attendere che il file può essere eliminato e quindi eliminarlo e spostare l'altro file.

Per fare questo, si potrebbe verificare, se v'è un handle aperto sul file, ma questo ha bisogno di codice non gestito. Un altro modo sarebbe quello di utilizzare la methode dalla risposta di questa domanda: Is there a way to check if a file is in use?

protected virtual bool IsFileLocked(FileInfo file) 
{ 
    FileStream stream = null; 

    try 
    { 
     stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
    } 
    catch (IOException) 
    { 
     //the file is unavailable because it is: 
     //still being written to 
     //or being processed by another thread 
     //or does not exist (has already been processed) 
     return true; 
    } 
    finally 
    { 
     if (stream != null) 
      stream.Close(); 
    } 

    //file is not locked 
    return false; 
} 

Prima di iniziare a eliminare il file si potrebbe

A) ciclo fino a quando il file può essere eliminato

while(IsFileLocked(f)) { Thread.Sleep(100); } 

o B) annullare

if (IsFileLocked(f)) { return; } 

Se si sceglie di A o B dipende sulle tue esigenze.

+0

Due parole: 'Condizioni di gara' – asawyer

Problemi correlati