Я прочитал предложенные посты при написании заголовка моего вопроса, но ничего не мог поделать. Код выглядит как мой, но я делаю что-то, что может быть не так. Также я хотел бы добавить несколько вопросов во время этого хе-хе.
Я пишу программу, которая будет запускать 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
}
}