использовать FileSystemWatcher для запуска события, а затем удалить вновь созданный файл? - PullRequest
2 голосов
/ 29 сентября 2010

У меня есть служба Windows, использующая 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);
}

Ответы [ 4 ]

1 голос
/ 01 июня 2011

Проблема не с FileSystemWatcher.Это с Image.FromFile(FilePath).Этот статический метод ведет себя очень плохо и оставляет блокировку файла даже после его удаления до следующей сборки мусора.Попробуйте это в вашем методе печати, чтобы получить изображение:

Image.FromStream(new MemoryStream(File.ReadAllBytes(FilePath)))
1 голос
/ 30 сентября 2010

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());
        }
    }
}
0 голосов
/ 30 сентября 2010

По умолчанию FSW запускает несколько событий во время создания файла, а не только когда файл вставляется в файловую систему.Чтобы минимизировать этот эффект, я установил:

FSW.NotifyFilter  =  NotifyFilters.FileName;

Также программа FSW запускает это событие при первом создании файла, а не при полной его загрузке в файловую систему.Если у вас большой файл, то между запуском этого события и файлом, фактически доступным для использования, будет определенная задержка.Там нет FSW даже, который говорит вам, когда файл был полностью записан.Чтобы обойти это, я использую повторный цикл, чтобы открыть файл для исключительных ошибок чтения и перехвата с помощью try / catch.И продолжайте пытаться загрузить файл, пока я не преуспею (или я не достигну предела повторных попыток), и немного посплю, когда у меня не получится.

Если вы немного погуглите, вы найдете множество решений, чтобы обойти ограничения FSW

0 голосов
/ 30 сентября 2010

Убить MyDoc, я думаю, что это то, что держит файл в использовании

...