2010-09-29 63 views
2

我有一个Windows服务使用FileSystemWatcher监视文件夹,打印添加的图像,然后在打印后删除图像。使用FileSystemWatcher来触发事件,然后删除新创建的文件?

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

的问题是,我得到抛出Error: System.IO.IOException: The process cannot access the file because it is being used by another process.不同的是该文件正在由另一个进程使用,当我尝试将其删除。我猜这是因为FileSystemWatcher保留了一些对它的引用。任何想法在这里做什么,打印后删除文件?

编辑:

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

我申请使用块建议,这个功能太,也感动了删除这一功能是事件处理程序: 之前没有从我的代码包含此功能mydoc.EndPrint,以确保与文件的所有关系都被切断,这似乎是个窍门。

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

使用['FileMon'(http://technet.microsoft.com/en-us/sysinternals/bb896642.aspx),看看哪些进程正在锁定文件。 – Oded 2010-09-29 19:57:13

回答

1

的PrintDocument实现IDisposable,你需要确保它释放它的文件句柄通过在使用块包装它。

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

没有这个运气。同样的错误。 '错误:System.IO.IOException:进程无法访问文件'C:\ ProcessBookImages \ 013Figure.GIF',因为它正在被另一个进程使用。' – xdumaine 2010-09-29 20:31:26

+0

我想那么它一定是监视器本身。我认为FileSystem观察器持有对文件的引用,因为Changed事件在Created事件之前触发。尝试将代码移至Created事件。 – 2010-09-29 20:37:47

+0

不,据此 - http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created.aspx - 我最后的评论是不正确的。 – 2010-09-29 20:40:29

0

杀mydoc,我认为这是保持在文件中使用

0

默认情况下,FSW触发多个事件正在创建的文件,同时,不只是当文件被插入到文件系统。为了尽量减少这种影响我设置:

FSW.NotifyFilter = NotifyFilters.FileName; 

另外,FSW时将触发第一个创建的文件,而不是当它已经完全加载到文件系统这一事件。如果你有一个大文件,那么在这个事件触发和实际可用的文件之间会有明显的时间延迟。甚至没有FSW告诉你文件被完全写入的时间。为了解决这个问题,我使用了一个重试循环来打开该文件,以独占阅读并用try/catch捕获错误。并继续尝试加载文件,直到我成功(或者我达到了重试限制),并在失败时睡一会儿。

如果谷歌了一下周围,你会发现很多的解决方案的周边FSW限制

1

的问题是不是与FileSystemWatcher获得。它与Image.FromFile(FilePath)。该静态方法行为非常糟糕,即使将其置于下一个垃圾收集之后,也会在文件上留下锁定。在您的打印方法试试这个来获取图像:

Image.FromStream(new MemoryStream(File.ReadAllBytes(FilePath))) 
相关问题