使用FileSystemWatcher触发事件,然后删除新创建的文件?

时间:2010-09-29 19:49:29

标签: c# windows-services filesystemwatcher

我有一个使用FileSystemWatcher的Windows服务来监控文件夹,打印添加的图像,然后在打印后删除图像。

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

4 个答案:

答案 0 :(得分:1)

PrintDocument实现了IDisposable,您需要确保它通过将其包装在using块中来释放它的文件句柄。

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

答案 1 :(得分:1)

问题不在于FileSystemWatcher。这是Image.FromFile(FilePath)。该静态方法表现非常糟糕,即使在将文件处理到下一次垃圾收集之后也会对文件进行锁定。在您的打印方法中尝试此操作以获取图像:

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

答案 2 :(得分:0)

杀死mydoc,我认为这就是保存文件的原因

答案 3 :(得分:0)

默认情况下,FSW会在创建文件时触发多个事件,而不仅仅是在文件插入文件系统时触发。为了尽量减少这种影响,我设置了:

FSW.NotifyFilter  =  NotifyFilters.FileName;

此外,FSW在首次创建文件时触发此事件,而不是在完全加载到文件系统中时触发此事件。如果您有一个大文件,那么在此事件触发和实际可供使用的文件之间会有明显的时间延迟。甚至没有FSW告诉您文件何时完全写入。为了解决这个问题,我使用重试循环来打开文件以使用try / catch来读取和捕获错误。并继续尝试加载文件,直到我成功(或我达到重试限制)并在我失败时稍微睡觉。

如果你稍微谷歌,你会找到许多解决FSW限制的解决方案