FileSystemWatcher и таймер вместе - PullRequest
       16

FileSystemWatcher и таймер вместе

0 голосов
/ 06 сентября 2018

Я прочитал предложенные посты при написании заголовка моего вопроса, но ничего не мог поделать. Код выглядит как мой, но я делаю что-то, что может быть не так. Также я хотел бы добавить несколько вопросов во время этого хе-хе.

Я пишу программу, которая будет запускать FileSystemWatcher и Timer вместе. Когда пользователь нажимает кнопку запуска, он запускает Timer и FileSystemWatcher.

Пока FileSystemWatcher отслеживает папку, Timer работает. Если файл не получен, ничего не происходит. Если файл создан, поместите его в событие OnCreated и перезапустите Timer.

После того, как файл (ы) был (были) создан и истек таймер, он начинает работу над классом FileProcessor.

Я видел много образцов класса FileProcessor, подходящих для конкретных нужд, и это то, что я сделал с моими. Изменен, чтобы посещать мои реквизиты.

Итак, вместо того, чтобы запускать задание в тот момент, когда задание ставится в очередь, я жду, пока не истечет Timer, и затем приступаю к обработке.

До сих пор все идет хорошо, но вот что происходит: Когда класс FileProcessor выполняет свою работу, FileSystemWatcher прекращает мониторинг папки. После завершения потока FileProcessor файл не обнаружен, таймер перезапускается нормально. Я хотел бы попросить помощи, чтобы увидеть, если что-то не так с этим, если я должен использовать другой компонент, а не FileSystemWatcher.

Кроме того, вопрос с этим вопросом: я хочу обнаружить файлы, созданные во время работы программы, и обработать их позже. Для этого я добавил отдельный счетчик, чтобы перехватить исходный счетчик очереди до того, как цикл начнет выходить из очереди. Это хороший подход?

Заранее спасибо!

Код формы:

   using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Telerik.WinControls;


namespace DI_Plot_2018
{
    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        FileSystemWatcher InputFileWatcher;
        FileProcessor TIFFProcessor;
        static Timer timer1;
        bool RestartTimer;
        LoadInternalSettings InternalSettings;
        double CurrentCounter;        
        public RadForm1()
        {            
            InitializeComponent();
            RestartTimer = false;
            InternalSettings = new LoadInternalSettings();
            //counter = Int32.Parse(InternalSettings.Timer);
            timer1 = new Timer();
            timer1.Tick += new EventHandler(SecondElapsed);
            timer1.Enabled = false;
            TIFFProcessor = new FileProcessor();
            LoadControls(InternalSettings);
        }
        DateTime start;
        double s;

        private void CountDown()
        {
            start = DateTime.Now;
            s = Double.Parse(InternalSettings.Timer);            
            timer1.Start();
        }

        private void SecondElapsed(object sender, EventArgs e)
        {
            double remainingSeconds = s - (DateTime.Now - start).TotalSeconds;            
            if(RestartTimer == true)
            {
                timer1.Stop();
                CountDown();
                RestartTimer = false;
            }
            else if (remainingSeconds <= 0)
            {
                timer1.Stop();
                if(TIFFProcessor.FilesQueue.Count > 0)
                {
                    TIFFProcessor.FireProcessing(CurrentCounter);
                }                
                CountDown();
            }
            var x = TimeSpan.FromSeconds(remainingSeconds);
            CurrentCounter = x.Seconds;
            TimerTextBox.Text = x.Seconds.ToString();
        }
        private void FileCreated(Object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Created)
            {
                TIFFProcessor.EnqueueJob(e.FullPath, CurrentCounter);
                RestartTimer = true;
            }
        }
        private void ButtonChangedEventHandler(object sender, EventArgs e)
        {
            Telerik.WinControls.UI.RadButton bt = sender as Telerik.WinControls.UI.RadButton;
            string buttonName = (String)bt.Name;
            SwitchButtonImage buttonImageSwitch;
            switch (buttonName)
            {
                case "StartButton":
                    {
                        InputFileWatcher = new FileSystemWatcher(InputFolderTextBox.Text);
                        InputFileWatcher.Created += new FileSystemEventHandler(FileCreated);
                        InputFileWatcher.Filter = "*.tif";
                        InputFileWatcher.EnableRaisingEvents = true;
                        StopButton.Enabled = true;
                        StartButton.Enabled = false;
                        CountDown();
                        //TimerStart();
                        break;
                    }
                case "StopButton":
                    {
                        InputFileWatcher.EnableRaisingEvents = false;
                        timer1.Stop();
                        StopButton.Enabled = false;
                        StartButton.Enabled = true;
                        break;
                    }
                case "ImageRotationButton":
                    {
                        buttonImageSwitch = new SwitchButtonImage(ImageRotationButton, "ImageRotationIndex");
                        break;
                    }
                case "ImageOrientationButton":
                    {
                        buttonImageSwitch = new SwitchButtonImage(ImageOrientationButton, "ImageOrientationIndex");
                        break;
                    }
                case "InputFolderBrowseButton":
                    {
                        InputFolderTextBox.Text = new ItemSaveToConfig.SelectFolderSaveProperty(InputFolderTextBox.Text, "Select the input folder", "InputFolder").folderSelect;
                        break;
                    }
                case "OutputFolderBrowseButton":
                    {
                        OutputFolderTextBox.Text = new ItemSaveToConfig.SelectFolderSaveProperty(OutputFolderTextBox.Text, "Select the output folder", "OutputFolder").folderSelect;
                        break;
                    }
            }
        }
        private void LoadControls(LoadInternalSettings Settings)
        {
            InputFolderTextBox.Text = InternalSettings.InputFolder;
            OutputFolderTextBox.Text = InternalSettings.OutputFolder;
            NumberOfZonesTextBox.Text = InternalSettings.NumberOfZones;
            FirstZoneWidthTextBox.Text = InternalSettings.FirstZoneWidth;
            LastZoneWidthTextBox.Text = InternalSettings.LastZoneWidth;
            ZoneAreaWidthTextBox.Text = InternalSettings.ZoneAreaWidth;
            ZoneAreaHeightTextBox.Text = InternalSettings.ZoneAreaHeight;
            ZoneWidthTextBox.Text = InternalSettings.ZoneWidth;
            TimerTextBox.Text = InternalSettings.Timer;
            ZoneWidthTextBox.Text = InternalSettings.ZoneWidth;
            ImageRotationButton.ChangeClickCountFromConfigFile(Int32.Parse(InternalSettings.ImageRotationIndex));
            ImageOrientationButton.ChangeClickCountFromConfigFile(Int32.Parse(InternalSettings.ImageOrientationIndex));
            //xmlRotateFront.ChangeClickCountFromConfigFile(internalSettings.XMLtoPPFRotateFrontIndex);
            var RotatePreview = new SwitchButtonImage(ImageRotationButton, "ImageRotationIndex");
            var OrientationPreview = new SwitchButtonImage(ImageOrientationButton, "ImageOrientationIndex");
        }
        private void TextBoxChangedEventHandler(object sender, EventArgs e)
        {
            Telerik.WinControls.UI.RadTextBox TxtBx = sender as Telerik.WinControls.UI.RadTextBox;
            string TxtName = TxtBx.Name;
            switch (TxtName)
            {
                case "NumberOfZonesTextBox":
                    {
                        NumberOfZonesTextBox.Text = new ItemSaveToConfig.ChangeAndSaveTextBox(NumberOfZonesTextBox.Text, "NumberOfZones", false).TextToApply;
                        break;
                    }
                case "ZoneWidthTextBox":
                    {
                        ZoneWidthTextBox.Text = new ItemSaveToConfig.ChangeAndSaveTextBox(ZoneWidthTextBox.Text, "ZoneWidth", false).TextToApply;
                        break;
                    }
                case "FirstZoneWidthTextBox":
                    {
                        ZoneWidthTextBox.Text = new ItemSaveToConfig.ChangeAndSaveTextBox(FirstZoneWidthTextBox.Text, "FirstZoneWidth", false).TextToApply;
                        break;
                    }
                case "LastZoneWidthTextBox":
                    {
                        ZoneWidthTextBox.Text = new ItemSaveToConfig.ChangeAndSaveTextBox(LastZoneWidthTextBox.Text, "LastZoneWidth", false).TextToApply;
                        break;
                    }
            }


        }
        private void RadForm1_FormClosed(object sender, FormClosedEventArgs e)
        {
            timer1.Stop();
            new ItemSaveToConfig.SelectItemSaveProperty("Timer", TimerTextBox.Text.ToString());
            //WaitingTimer.Stop();
            Environment.Exit(0);
        }
    }
}

Код FileProcessor:

    using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Timers;
using DI_Plot_2018.IZData;

namespace DI_Plot_2018
{
    class FileProcessor : IDisposable
    {
        // Create an AutoResetEvent EventWaitHandle
        private EventWaitHandle eventWaitHandle = new AutoResetEvent(false);
        private readonly object locker = new object();
        private Thread worker;                
        public Queue<string> FilesQueue = new Queue<string>();
        private Queue<KeyValuePair<string, List<string>>> JobsQueue = new Queue<KeyValuePair<string, List<string>>>();
        private Dictionary<string, List<string>> FullJob = new Dictionary<string, List<string>>();
        #region IDisposable Members
        public FileProcessor()
        {
            worker = new Thread(new ThreadStart(Work));
            worker.IsBackground = true;
        }
        public void FireProcessing(double counter)
        {
            int filesQueuedCounter = FilesQueue.Count;
            if (counter <= 0) //Timer is over, proceed with execution
            {
                lock(locker)
                {                    
                    while (filesQueuedCounter > 0)
                    {
                        string currFilename = FilesQueue.Dequeue(); //Dequeue filename
                        JobDetails CurrentJobInfo = new JobDetails(currFilename); //Get information about the job 
                        //Checking if dict already has the key - if it does, add the filename at the key position
                        if (FullJob.ContainsKey(CurrentJobInfo.JobNameWithoutColor))
                            FullJob[CurrentJobInfo.JobNameWithoutColor].Add(currFilename);
                        else //if it doesn't, add the new key and start the value (List<string>) with the current filename
                            FullJob.Add(CurrentJobInfo.JobNameWithoutColor, new List<string>() { currFilename });
                        filesQueuedCounter--;
                    }//End while loop - Dequeue all files
                    foreach (var item in FullJob) //Enqueue files in a jobs queue (KeyValuePair queue)
                    {
                        JobsQueue.Enqueue(item);
                    }
                    eventWaitHandle.Set();                    
                    worker.Start();
                }                                    

            }
        }
        public void EnqueueJob(string FileName, double counter)
        {            
            if(counter > 0)
            {
                lock(locker)
                {
                    FilesQueue.Enqueue(FileName);
                }                
            }             
        }
        private void Work()
        {
            while(true)
            {
                KeyValuePair<string, List<string>> JobToRun = new KeyValuePair<string, List<string>>();
                lock (locker)
                {
                    if(JobsQueue.Count > 0)
                    {
                        JobToRun = JobsQueue.Dequeue();
                        if (JobToRun.Key == null) return;
                    }
                    if(JobToRun.Key != null)
                    {
                        ProcessJob(JobToRun);
                    }
                    else
                    {
                        eventWaitHandle.WaitOne();
                    }
                }
            }
        }
        private void ProcessJob(KeyValuePair<string,List<string>> currJob)
        {
            string x = string.Empty;

        }
        public void Dispose()
        {
            // Signal the FileProcessor to exit
            FilesQueue.Enqueue(null);
            JobsQueue.Enqueue(new KeyValuePair<string, List<string>>("aa", new List<string>() { "aa"}));
            // Wait for the FileProcessor's thread to finish
            worker.Join();
            // Release any OS resources
            eventWaitHandle.Close();
        }
        #endregion
    }
}
...