none
FileSystemWatcher после полной записи файла RRS feed

  • Вопрос

  • Доброе время суток.

    Вопрос по поводу FileSystemWatcher. Задача состоит в следующем. Программа используя FileSystemWatcher следит за папкой для срабатывания при записи нового файла. При появлении нового файла в этой папке программа его конвертирует. Проблема в том что моя программа пытается это сделать ранее чем файл полностью скопирован в нее.  Вот код:
    private void fileSystemWatcher_Noverotajs_Created(object sender, FileSystemEventArgs e)
            {
                FailuIzmainas(e);
            }
    
     private void FailuIzmainas(FileSystemEventArgs e)
            {
                if (e.ChangeType == WatcherChangeTypes.Created && e.Name.Substring(0, 2) != "~$")
                {
                   
                        string Paplasinajums = System.IO.Path.GetExtension(e.FullPath);
    
                        switch (Paplasinajums)
                        {
                            case ".doc":
                                KonvertacijaUnPazinojums(e);
                                break;
                            case ".rtf":
                                KonvertacijaUnPazinojums(e);
                                break;
                            default: break;
                        }
    
                    
    
                }
            }
    this.fileSystemWatcher_Noverotajs.EnableRaisingEvents = true;
                this.fileSystemWatcher_Noverotajs.IncludeSubdirectories = true;
                this.fileSystemWatcher_Noverotajs.SynchronizingObject = this;
                this.fileSystemWatcher_Noverotajs.Created += new System.IO.FileSystemEventHandler(this.fileSystemWatcher_Noverotajs_Created);
                this.fileSystemWatcher_Noverotajs.Changed += new System.IO.FileSystemEventHandler(this.fileSystemWatcher_Noverotajs_Created);
                /
    В кратце все должно быть так: появляется новый файл в папке  мы его конвертирумум. Все действия происходит только после полной записи файла, в моем случае файли создается при помощью принтера - вывод в файл. По форумам единственный способ это сделать сводится к созданию таймера который проверяет способностьоткрыть файл в режиме записи и если удачно то только после этого пробовать делать с ним какие либо действия. Есть ли какие либо другие способы?
    • Перемещено Tagore Bandlamudi 1 октября 2010 г. 22:58 MSDN Forums consolidation (От:Visual C#)
    4 февраля 2010 г. 11:26

Ответы

  •         public void OnCreatedFile(object obj, FileSystemEventArgs e)
            {
                Thread t = new Thread(new ParameterizedThreadStart(FailuIzmainas));
                t.Start(e);
            }
    
            void FailuIzmainas(object exx)
            {
                FileSystemEventArgs e = exx as FileSystemEventArgs;
                if (e.ChangeType == WatcherChangeTypes.Created && e.Name.Substring(0, 2) != "~$")
                {
                    int GaidisanasLaiks = 0;
    
    
                    while (true)
                    {
                        try
                        {
                            string Paplasinajums = System.IO.Path.GetExtension(e.FullPath);
                            FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None);
                            fs.Close();
                            fs.Dispose();
                            switch (Paplasinajums)
                            {
                                case ".doc":
                                    KonvertacijaUnPazinojums(e);
                                    break;
                                case ".rtf":
                                    KonvertacijaUnPazinojums(e);
                                    break;
                                default: break;
                            }
                            break;
                        }
                        catch (Exception ex)
                        {
                            GaidisanasLaiks = GaidisanasLaiks + 1000;
                            if (GaidisanasLaiks > 10000000)
                            { throw new ApplicationException(); }
                            Thread.Sleep(100);
                        }
                    }
                }
            }
    • Помечено в качестве ответа I.Vorontsov 15 февраля 2010 г. 8:35
    11 февраля 2010 г. 13:17
  • Thread.Sleep(100) останавливает только текущий поток, т.е. тот поток из которого этот метод был вызван. Я вызвал Sleep для того, чтобы поток не слишком часто пытался открыть файл.
    Да, при создании 10 ти файлов будет 10 потоков.
    • Помечено в качестве ответа I.Vorontsov 15 февраля 2010 г. 8:35
    11 февраля 2010 г. 14:29
  •         public void OnCreatedFile(object obj, FileSystemEventArgs e)
            {
                Thread t = new Thread(new ParameterizedThreadStart(FailuIzmainas));
                t.Start(e);
            }
    
            void FailuIzmainas(object exx)
            {
                FileSystemEventArgs e = exx as FileSystemEventArgs;
                
                if (e.ChangeType == WatcherChangeTypes.Created && e.Name.Substring(0, 2) != "~$")
                {
                    int GaidisanasLaiks = 0;
    
    
                    while (GaidisanasLaiks < 10000000)
                    {
                        try
                        {
                            string Paplasinajums = System.IO.Path.GetExtension(e.FullPath);
                            FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None);
                            fs.Close();
                            fs.Dispose();
                            switch (Paplasinajums)
                            {
                                case ".doc":
                                    KonvertacijaUnPazinojums(e);
                                    return; //Exit
                                case ".rtf":
                                    KonvertacijaUnPazinojums(e);
                                    return;
                                default: break;
                            }
                            break;
                        }
                        catch (FileNotFoundException fnfex)
                        {
                            return;
                        }
                        catch (IOException io)
                        {
                            GaidisanasLaiks = GaidisanasLaiks + 1000;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            return;
                        }
                        Thread.Sleep(100);
                    }
                }
            }

    • Помечено в качестве ответа Art4iks 16 февраля 2010 г. 10:10
    11 февраля 2010 г. 14:54
  • Есстественно, не устраняет, он будет помещать в очередь сообщения о последней записи, в зависимости от загруженности FileSystemWatcher при записи одного файла может появляться несколько уведомлений LastWrite. На форумах вам правильно сказали, нужно создать отдельный поток, который периодически будет пытаться открыть файл для чтения.. Это будет работать всегда, если поток, открываемый принтером будет только для записи, а не для чтения-записи.
    Вот примерная реализация
    http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/5695490c-a644-48a3-be2b-cfb762cf4765
    • Помечено в качестве ответа I.Vorontsov 15 февраля 2010 г. 8:35
    10 февраля 2010 г. 15:08

Все ответы

  • Возможно поможет:

    fileSystemWatcher_Noverotajs.NotifyFilter = NotifyFilters.LastWrite;

    4 февраля 2010 г. 13:23
  • Это не устраняет проблему с преждевременным началом конвертации.   
    10 февраля 2010 г. 14:46
  • Есстественно, не устраняет, он будет помещать в очередь сообщения о последней записи, в зависимости от загруженности FileSystemWatcher при записи одного файла может появляться несколько уведомлений LastWrite. На форумах вам правильно сказали, нужно создать отдельный поток, который периодически будет пытаться открыть файл для чтения.. Это будет работать всегда, если поток, открываемый принтером будет только для записи, а не для чтения-записи.
    Вот примерная реализация
    http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/5695490c-a644-48a3-be2b-cfb762cf4765
    • Помечено в качестве ответа I.Vorontsov 15 февраля 2010 г. 8:35
    10 февраля 2010 г. 15:08
  • Столкнулся с проблемой создания многопоточнести своей программы.  Переделал клас FailuIzmainas теперь он должен ждать указанное время за которое файл должен быть закрыт и свободен для использования.

    void FailuIzmainas(FileSystemEventArgs e) { if (e.ChangeType == WatcherChangeTypes.Created && e.Name.Substring(0, 2) != "~$") { int GaidisanasLaiks = 0; while (true) { try { string Paplasinajums = System.IO.Path.GetExtension(e.FullPath); FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None); fs.Close(); fs.Dispose(); switch (Paplasinajums) { case ".doc": KonvertacijaUnPazinojums(e); break; case ".rtf": KonvertacijaUnPazinojums(e); break; default: break; } break; } catch(Exception ex) { GaidisanasLaiks = GaidisanasLaiks + 1000; if (GaidisanasLaiks > 10000000) { throw new ApplicationException(); } } } } }
    Как его теперь положить в отдельный поток?   Если он будет в отдельном потоке я так понемаю надо будет и переделать while блок под использование Thread.Sleep
    11 февраля 2010 г. 13:00
  •         public void OnCreatedFile(object obj, FileSystemEventArgs e)
            {
                Thread t = new Thread(new ParameterizedThreadStart(FailuIzmainas));
                t.Start(e);
            }
    
            void FailuIzmainas(object exx)
            {
                FileSystemEventArgs e = exx as FileSystemEventArgs;
                if (e.ChangeType == WatcherChangeTypes.Created && e.Name.Substring(0, 2) != "~$")
                {
                    int GaidisanasLaiks = 0;
    
    
                    while (true)
                    {
                        try
                        {
                            string Paplasinajums = System.IO.Path.GetExtension(e.FullPath);
                            FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None);
                            fs.Close();
                            fs.Dispose();
                            switch (Paplasinajums)
                            {
                                case ".doc":
                                    KonvertacijaUnPazinojums(e);
                                    break;
                                case ".rtf":
                                    KonvertacijaUnPazinojums(e);
                                    break;
                                default: break;
                            }
                            break;
                        }
                        catch (Exception ex)
                        {
                            GaidisanasLaiks = GaidisanasLaiks + 1000;
                            if (GaidisanasLaiks > 10000000)
                            { throw new ApplicationException(); }
                            Thread.Sleep(100);
                        }
                    }
                }
            }
    • Помечено в качестве ответа I.Vorontsov 15 февраля 2010 г. 8:35
    11 февраля 2010 г. 13:17
  • Если в папку кинуть 10 файлов то создаются 10 потоков я так понемаю. И  Thread.Sleep(100); останавливает только тот поток который определяет что файл занять либо он останавливает все потоки до времени когда освобождается первый скопированный файл?
     
    11 февраля 2010 г. 14:25
  • Thread.Sleep(100) останавливает только текущий поток, т.е. тот поток из которого этот метод был вызван. Я вызвал Sleep для того, чтобы поток не слишком часто пытался открыть файл.
    Да, при создании 10 ти файлов будет 10 потоков.
    • Помечено в качестве ответа I.Vorontsov 15 февраля 2010 г. 8:35
    11 февраля 2010 г. 14:29
  • Спасибо. Но у меня еще есть вопрос. Делаю блок while (true) таким образом что бы он работал до тех пор пока файл неосвободится, до этого он пытался только определенное количество раз. Я думаю реолизовать блок catch таким образом
     catch(Exception ex)
                        {
                            if (ex is IOException)
                            {
                                Thread.Sleep(1000);
                            }
                            if (ex is FileNotFoundException)
                            {
    
                            }
                            
                        }
    С этого вытекает что если файл занят ждем 1 секунду и проверяем повторно, но если файл удален то нам надо закрыть поток. Как правельно ето сделать?

    плюс ко всему возникла еще одна проблема. Если файл не занят запускается конвертация файла

    switch (Paplasinajums)
                            {
                                    
                                case ".doc":
                                    KonvertacijaUnPazinojums(e);
                                    break;
                                case ".rtf":
                                    KonvertacijaUnPazinojums(e);
                                    break;
                                default: break;
                            }
    но получается конвертация пытается запустится еще безконечное количество раз, предпологаю, что после комманды  KonvertacijaUnPazinojums(e); нужно закрывать поток как и в случае когда файл удален но в Thread ненашов метода закрытия потока.
    11 февраля 2010 г. 14:45
  •         public void OnCreatedFile(object obj, FileSystemEventArgs e)
            {
                Thread t = new Thread(new ParameterizedThreadStart(FailuIzmainas));
                t.Start(e);
            }
    
            void FailuIzmainas(object exx)
            {
                FileSystemEventArgs e = exx as FileSystemEventArgs;
                
                if (e.ChangeType == WatcherChangeTypes.Created && e.Name.Substring(0, 2) != "~$")
                {
                    int GaidisanasLaiks = 0;
    
    
                    while (GaidisanasLaiks < 10000000)
                    {
                        try
                        {
                            string Paplasinajums = System.IO.Path.GetExtension(e.FullPath);
                            FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None);
                            fs.Close();
                            fs.Dispose();
                            switch (Paplasinajums)
                            {
                                case ".doc":
                                    KonvertacijaUnPazinojums(e);
                                    return; //Exit
                                case ".rtf":
                                    KonvertacijaUnPazinojums(e);
                                    return;
                                default: break;
                            }
                            break;
                        }
                        catch (FileNotFoundException fnfex)
                        {
                            return;
                        }
                        catch (IOException io)
                        {
                            GaidisanasLaiks = GaidisanasLaiks + 1000;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            return;
                        }
                        Thread.Sleep(100);
                    }
                }
            }

    • Помечено в качестве ответа Art4iks 16 февраля 2010 г. 10:10
    11 февраля 2010 г. 14:54
  • Подскажите пожалуйста, как вообще работает FileSystemWatcher ?

    Допустим я настроил его как в примере этой темы, но сам никаких дополнительных потоков не создаю, просто подписался на события создания и изменения.

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

    5 декабря 2012 г. 11:56