2010-09-29 30 views
2

J'ai un service Windows utilisant un FileSystemWatcher pour surveiller un dossier, imprimer des images ajoutées, puis supprimer l'image après l'impression.en utilisant FileSystemWatcher pour déclencher l'événement, puis supprimer le fichier nouvellement créé?

private void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      FileSystemWatcher Watcher = new FileSystemWatcher(); 
      Watcher.Path = @"C:\Images"; 
      Watcher.Created += new FileSystemEventHandler(Watcher_Changed); 
      Watcher.EnableRaisingEvents = true; 
     } 

     private void Watcher_Changed(object sender, FileSystemEventArgs e) 
     { 
      try 
      { 
       PrintDocument myDoc = new PrintDocument(); 
       myDoc.PrintPage += new PrintPageEventHandler(print); 
       FilePath = e.FullPath; 
       myDoc.PrinterSettings.PrinterName = @"\\Network Printer"; 
       myDoc.Print(); 
       using (StreamWriter sw = new StreamWriter("C:\\error.txt")) 
       { 
        sw.WriteLine("Printed File: " + FilePath); 
       } 
       File.Delete(e.FullPath); 
      } 
      catch(Exception excep) 
      { 
       using (StreamWriter sw = new StreamWriter("C:\\error.txt")) 
       { 
        sw.WriteLine("Error: " + excep.ToString()); 
       } 
      } 
     } 

Le problème est que je reçois l'exception jetée Error: System.IO.IOException: The process cannot access the file because it is being used by another process. que le fichier est utilisé par un autre processus lorsque je tente de le supprimer. Je suppose que c'est parce que FileSystemWatcher garde une sorte de référence. Une idée sur ce qu'il faut faire ici, pour supprimer le fichier après qu'il soit imprimé?

Edit: N'a pas inclure cette fonction de mon code avant:

private void print(object sender, PrintPageEventArgs e) 
     { 
      try 
      { 
       using (Image i = Image.FromFile(FilePath)) 
       { 
        Point p = new Point(0, 0); 
        e.Graphics.DrawImage(i, p); 
       } 
      } 
      catch(Exception exep) 
      { 
       throw exep; 
      } 
     } 

J'ai appliqué l'aide de suggestion de bloc à cette fonction aussi, mais aussi déplacé la suppression de cette fonction qui est gestionnaire d'événements pour mydoc.EndPrint, pour assurer que tous les liens vers le fichier ont été coupés, et cela semble faire l'affaire.

void myDoc_EndPrint(object sender, PrintEventArgs e) 
{ 
    File.Delete(FilePath); 
} 
+0

Utilisez [ 'FileMon'] (http://technet.microsoft.com/en-us/sysinternals/bb896642.aspx) pour voir quels sont les processus verrouillent le fichier. – Oded

Répondre

1

PrintDocument implémente IDisposable, vous devez vous assurer qu'il libère son descripteur de fichier en l'enveloppant dans un bloc à l'aide.

private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     FileSystemWatcher Watcher = new FileSystemWatcher(); 
     Watcher.Path = @"C:\Images"; 
     Watcher.Created += new FileSystemEventHandler(Watcher_Changed); 
     Watcher.EnableRaisingEvents = true; 
    } 
private void Watcher_Changed(object sender, FileSystemEventArgs e) 
{ 
    try 
    { 
     using (PrintDocument myDoc = new PrintDocument()) 
     { 
      myDoc.PrintPage += new PrintPageEventHandler(print); 
      FilePath = e.FullPath; 
      myDoc.PrinterSettings.PrinterName = @"\\Network Printer"; 
      myDoc.Print(); 
      using (StreamWriter sw = new StreamWriter("C:\\error.txt")) 
      { 
       sw.WriteLine("Printed File: " + FilePath); 
      } 
     } 
     File.Delete(e.FullPath); 
    } 
    catch(Exception excep) 
    { 
     using (StreamWriter sw = new StreamWriter("C:\\error.txt")) 
     { 
      sw.WriteLine("Error: " + excep.ToString()); 
     } 
    } 
} 
+0

Pas de chance avec ça. Même erreur 'Erreur: System.IO.IOException: Le processus ne peut pas accéder au fichier 'C: \ ProcessBookImages \ 013Figure.GIF' car il est utilisé par un autre processus.' – xdumaine

+0

Je suppose que cela doit être le surveillant lui-même. Je pense que l'observateur FileSystem contient une référence au fichier car l'événement Changed déclenche avant l'événement Created. Essayez de déplacer le code vers l'événement Created. –

+0

Non, selon ce - http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created.aspx - mon dernier commentaire n'était pas correct. –

0

Tuez mondoc, je pense que c'est ce que garder le fichier en cours d'utilisation

0

Par défaut, les FSW multiples incendies événements alors que le fichier est en cours de création, non seulement lorsque le fichier est inséré dans le système de fichiers. Pour minimiser cet effet, je mets:

FSW.NotifyFilter = NotifyFilters.FileName; 

Aussi les FSW incendies cet événement lorsque le fichier est créé et non lorsqu'il est complètement chargé dans le système de fichiers. Si vous avez un fichier volumineux, il y aura un délai distinct entre le déclenchement de cet événement et le moment où le fichier sera réellement disponible. Il n'y a même pas FSW qui vous indique quand le fichier a été complètement écrit. Pour contourner cela, j'utilise une boucle de réessais pour ouvrir le fichier pour une lecture exclusive et piéger les erreurs avec un try/catch. Et continuez à essayer de charger le fichier jusqu'à ce que je réussisse (ou que j'atteins une limite de réessai) et que je dorme un peu quand j'échoue.

Si vous surfez sur un peu, vous trouverez de nombreuses solutions pour se déplacer limites FSW

1

Le problème est pas avec le FileSystemWatcher. C'est avec Image.FromFile(FilePath). Cette méthode statique se comporte très mal et laisse un verrou sur le fichier même après qu'il est disposé jusqu'à la prochaine garbage collection. Essayez ceci dans votre méthode d'impression pour obtenir l'image:

Image.FromStream(new MemoryStream(File.ReadAllBytes(FilePath)))