我在集合(Dictionary>)上运行了一些可观察的操作,其中字符串是作业名称,List是与该作业名称相关的文件。
如果我将List转换为Observable,它将按列表元素的数量运行所有操作。因此,在所有操作后我都可以删除文件。
为了避免这种情况,我将Dictionary键转换为另一个observable。但是当我这样做时,我无法删除与密钥相关的文件(值(列表))。
这有什么解决方法吗?我知道一旦所有操作完成,它将会点击订阅。但由于它在键上运行(所以它不会重复)我没有要删除的有效文件。
我尽可能详细地发布代码。
任何输入都表示赞赏。谢谢
if (TIFFFiles.Count > 0 && ThreadRunning == false) //If there are files to be processed and nothing is already running
{
ThreadRunning = true;
var toObservable = TIFFFiles.ToObservable(); //Converting the current file list to an observable
cmb_ColorDelimiter.UIThread(() => cmb_tiffSelectedIndex = cmb_ColorDelimiter.SelectedIndex); //An int value
var ColorSeparator = new ColorSeparatorDefiner(cmb_tiffSelectedIndex).Delimiter;//An string value
var InfoFromFiles = new List<CMYKJobInformationForDictionarySorting>();//List for sorting
Dictionary<string, List<string>> AvailableJobsDictionary = new Dictionary<string, List<string>>(); //The dictionary where i sort the files received on TIFFFiles
for (int i = 0; i < TIFFFiles.Count; i++)
{
AvailableJobsDictionary = BuildJobsDict(TIFFFiles[i], ColorSeparator, AvailableJobsDictionary,InfoFromFiles); //The method that sorts the files from TIFFFiles
}
var observableKeys = AvailableJobsDictionary.Keys.ToObservable(); //Converting the dictiobary keys to an observable
foreach(var item in AvailableJobsDictionary) //Looping trough sorted jobs
{
//By iterating over the keys i can iterate only one time per job. If iterate over all TIFFFiles it will run operations by the number of elements available in TIFFFiles.
IObservable<string> query = from file in observableKeys
from WriteDefaultXML in Observable.Start(() => new PPFConverter.writeFinalXml(item.Key, tb_TIFFtoXMLOutputFolder.Text))
from ImageListSorted in Observable.Start(() => ImageBuilder(item.Value, ColorSeparator))
from DPI in Observable.Start(() => new ObtainDPI(item.Value.ElementAt(0)))
from IZDataInfo in Observable.Start(() => new IZAreaDataInfo(izAreaSettings.FrmIZArea_numberOfZones, izAreaSettings.FrmIZArea_zoneWidth,
izAreaSettings.FrmIZArea_firstZoneWidth, izAreaSettings.FrmIZArea_lastZoneWidth, izAreaSettings.FrmIZArea_zoneAreaWidth, izAreaSettings.FrmIZArea_zoneAreaHeight, DPI.DPI))
from RotateCMYK in Observable.Start(() => Rotate(ImageListSorted.CMYKmages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageRotationCount))
from RotateImposition in Observable.Start(() => Rotate(ImageListSorted.ImposedImages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageRotationCount))
from IZDraw in Observable.Start(() => InkZoneAreaImage(IZDataInfo.IzArea_ZoneAreaWidth, IZDataInfo.IzArea_ZoneAreaHeight))
from CMYKIZCalculation in Observable.Start(() => LevelCalc(IZDataInfo.IzArea_ZoneWidth, DPI.DPI, RotateCMYK.RotatedImgs, IZDraw.ZoneImage, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont))
from ImposedIZCalculation in Observable.Start(() => LevelCalc(IZDataInfo.IzArea_ZoneWidth, DPI.DPI, RotateImposition.RotatedImgs, IZDraw.ZoneImage, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont))
from CMYKResize in Observable.Start(() => ResizeCollection(RotateCMYK.RotatedImgs, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewWidth, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewHeight))
from ImpositionResize in Observable.Start(() => ResizeCollection(RotateImposition.RotatedImgs, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewWidth, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewHeight))
from CombineTHumbnail in Observable.Start(() => CombineImages(CMYKResize.ResizedImages, (bool)Properties.Settings.Default["TIFFtoXML_NegateImage"]))
from CreateComposedImage in Observable.Start(() => new SpotImageComposer(CombineTHumbnail.FinalCombinedImage, ImpositionResize.ResizedImages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont, ColorSeparator, tiffToXmlpngPreviewSettings.TIffToXml_UnknownSpotcolorHandling))
from FinalXMLWrite in Observable.Start(() => new WriteXMLData(WriteDefaultXML.finalXmlName,WriteDefaultXML.OutputFolder,CMYKIZCalculation,ImposedIZCalculation,CreateComposedImage.FinalImage,WriteDefaultXML.xmlDoc,InfoFromFiles,ColorSeparator,item.Value))
select file;
if((bool)Properties.Settings.Default["TIFFtoXML_DeleteInput"])
{
_subscription = query.Subscribe(f => System.IO.File.Delete(f)); //Wanted to delete the files
}
TIFFFiles.Clear();
ThreadRunning = false;
}
}
更新的代码:
public partial class Form1
{
Dictionary<string, List<string>> sortedJobs;
Subject<List<string>> jobsToRun;
private int cmb_tiffSelectedIndex;
public Form1()
{
InitializeComponent();
jobsToRun = new Subject<List<string>>();
sortedJobs = new Dictionary<string, List<string>>();
}
private void SecondElapsed(object sender, EventArgs e)
{
counter--;
if (counter == 0)
{
timer1.Stop();
counter = Int32.Parse(internalSettings.TIFFtoXML_MainTimer);
cmb_ColorDelimiter.UIThread(() => cmb_tiffSelectedIndex = cmb_ColorDelimiter.SelectedIndex); //An int value
foreach (var item in sortedJobs.Values) //Each list string contains information about an job and its respective files
{
jobsToRun.OnNext(item);
IObservable<List<string>> query = from currItem in jobsToRun
let ColorSeparator = new ColorSeparatorDefiner(cmb_tiffSelectedIndex).Delimiter
let JobInfo = new CMYKJobInformationForDictionarySorting(item.ElementAt(0), ColorSeparator)
let file = JobInfo.ConventionName
select currItem;
_subscription = query.Subscribe(x =>
{
if ((bool)Properties.Settings.Default["TIFFtoXML_DeleteInput"])
{
foreach (var currFile in x)
File.Delete(currFile);
//Wanted to delete the files
}
});
string r = string.Empty;
}
timer1.Start();
}
tb_MainTimer.Text = counter.ToString();
}
private void TIFFtoXMLEventHandler(object sender, FileSystemEventArgs e)
{
string fNameExt = Path.GetExtension(e.FullPath).ToUpper();
if (new GetAvailableFile(e.FullPath).fileReady)
{
if (fNameExt.Contains(".TIF"))
{
SortFilesOnArrival(e.FullPath, cmb_tiffSelectedIndex);
}
else if (fNameExt.Contains(".CIP") || fNameExt.Contains(".PPF"))
{
}
}
counter = Int32.Parse(internalSettings.TIFFtoXML_MainTimer);
// timer1.Stop();
timer1.Start();
}
private void SortFilesOnArrival(string currFile, int ColorDelimiterIndex)
{
var colorSeparator = new ColorSeparatorDefiner(ColorDelimiterIndex).Delimiter;
CMYKJobInformationForDictionarySorting InfoFromFiles = new CMYKJobInformationForDictionarySorting(currFile, colorSeparator);
if (sortedJobs.ContainsKey(InfoFromFiles.ConventionName))
{
sortedJobs[InfoFromFiles.ConventionName].Add(InfoFromFiles.OriginalFileName);
}
else
{
sortedJobs.Add(InfoFromFiles.ConventionName, new List<string>() { InfoFromFiles.OriginalFileName });
}
FilesCopiedInfo.Add(InfoFromFiles);
}
}
更新:我编辑了包括我所做的一切的最终代码=)!它最终工作,现在我只是设置一些细节(更多关于业务逻辑和工作流程)。我知道这远远不是好事,但就目前我决定要做的事情而言。我的下一个目标是对所有类型的文件进行单一订阅,并处理查询本身的不同情况;它会使事情变得更容易,并允许我用更少的代码做同样的事情。并提前感谢您的帮助。这就像是对我的Reactive Extensions的介绍嘿,我开始阅读和挖掘它。
public partial class Form1 : AsyncBaseDialog
{
private IDisposable CIP3Subscription = null;
static System.Windows.Forms.Timer timer1; //The timer is used but just for visual purposes - nothing is related to him
IObservable<FileSystemEventArgs> TIFFFilesCreated;
IObservable<FileSystemEventArgs[]> TIFFGroupFiles;
IObservable<FileSystemEventArgs> CIP3FilesCreated;
IObservable<FileSystemEventArgs[]> CIP3GroupFiles;
bool currStatus = (bool)Properties.Settings.Default["TIFFtoXML_EnabledConversion"]; //If the enable conversion checkbox is enabled, fire the observable
if(currStatus)
{
EnableTIFFtoXMLWatcher(currStatus);
EnableCIP3toTIFFWatcher(currStatus);
}
timer1 = new System.Windows.Forms.Timer();
timer1.Tick += new EventHandler(SecondElapsed);
timer1.Enabled = currStatus;
counter = Convert.ToInt32(Properties.Settings.Default.TIFFtoXML_MainTimer);
}
#region timerStuff
DateTime start;
double s;
private void CountDown()
{
start = DateTime.Now;
s = (double)counter;
timer1.Start();
}
private void SecondElapsed(object sender, EventArgs e)
{
double remainingSeconds = s - (DateTime.Now - start).TotalSeconds;
if (remainingSeconds <= 0)
{
timer1.Stop();
timer1.Interval = (int)counter;
timer1.Start();
CountDown();
}
var x = TimeSpan.FromSeconds(remainingSeconds);
tb_MainTimer.Text = x.Seconds.ToString();
}
#endregion
#region ObservableMethods //Methods i built in order to handle the observable behaviour
private IObservable<FileSystemEventArgs[]> CreateObjectForConvertAll(string inputFolder, string extension)
{
//I've a checkbox where the user selects "Convert all", and it will convert everything in the folder. Since i didn't wanted to repeat
//code by calling all methods again, this method returns me an object i can query
List<FileSystemEventArgs> tempList = new List<FileSystemEventArgs>(Directory.GetFiles(tb_TIFFtoXMLInputFolder.Text, extension, SearchOption.TopDirectoryOnly).ToList()
.Select(x => new FileSystemEventArgs(WatcherChangeTypes.Created, "", x)));
List<FileSystemEventArgs[]> fswArgsArrayList = new List<FileSystemEventArgs[]>();
fswArgsArrayList.Add(tempList.ToArray());
var finalObservable = fswArgsArrayList.ToArray();
var finalObservableNotArray = finalObservable.ToArray().ToObservable();
return finalObservableNotArray;
}
private IObservable<FileSystemEventArgs> CreateReactiveFSWInstance(string inputFolder, string fileFilter, bool checkBoxStatus)
{
//Creates the Reactive FSW instance
//checkBoxStatus => Enabled or not ; if the user enables the conversion, EnableRaisingEvents will be true
IObservable<FileSystemEventArgs> filesCreated =
Observable
.Using(
() =>
{
var fsw = new FileSystemWatcher(inputFolder)
{
EnableRaisingEvents = checkBoxStatus,
Filter = fileFilter
};
return fsw;
},
fsw => Observable.FromEventPattern
<FileSystemEventHandler, FileSystemEventArgs>(
h => fsw.Created += h,
h => fsw.Created -= h))
.Delay(TimeSpan.FromSeconds(0.1))
.Select(x => x.EventArgs);
return filesCreated;
}
private IObservable<FileSystemEventArgs[]> TIFFPublish(IObservable<FileSystemEventArgs> observable)
{
var GroupFiles =
observable
.Publish(fc =>
from w in fc.Window(() => fc.Throttle(TimeSpan.FromSeconds((double)counter)))
from fcs in w.ToArray()
select fcs);
return GroupFiles;
}
#endregion
private void StartCIP3ProcessingQuery(IObservable<FileSystemEventArgs[]> Files)
{
//query goes here...
}
private void StartTIFFProcessingQuery(IObservable<FileSystemEventArgs[]> Files)
{
//query goes here...
}
private void EnableTIFFtoXMLWatcher(bool status)
{
//Enable the reactive watcher for TIF files
TIFFFilesCreated = CreateReactiveFSWInstance(tb_TIFFtoXMLInputFolder.Text, "*.tif", status);
TIFFGroupFiles = TIFFPublish(TIFFFilesCreated);
StartTIFFProcessingQuery(TIFFGroupFiles);
}
private void EnableCIP3toTIFFWatcher(bool status)
{
//Enable the reactive watcher for CIP3 files
CIP3FilesCreated = CreateReactiveFSWInstance(tb_TIFFtoXMLInputFolder.Text, "*.*", status);
CIP3GroupFiles = TIFFPublish(CIP3FilesCreated);
StartCIP3ProcessingQuery(CIP3GroupFiles, false);
}
private void SubscriptionDisposal()
{
//Disposal methods
TIFFSubscription.Dispose();
CIP3Subscription.Dispose();
}
//Enable or disable the conversio, or convert all
private void CheckboxChangedEventHandler(object sender, EventArgs e)
{
CheckBox CurrChk = sender as CheckBox;
bool status = CurrChk.Checked;
switch (CurrChk.Name)
{
case "TIFFtoXML_chkConvertAll":
{
if(status)
{
cb_enableTIFFtoXML.Checked = true; //Enabling this checkbox triggers the other case and fires the FSW
var convertAllTIFFObj = CreateObjectForConvertAll(tb_TIFFtoXMLInputFolder.Text, "*.tif");
StartTIFFProcessingQuery(convertAllTIFFObj);
var convertAllCIP3Obj = CreateObjectForConvertAll(tb_TIFFtoXMLInputFolder.Text, "*.*");
StartCIP3ProcessingQuery(convertAllCIP3Obj,true);
CurrChk.Checked = false;
}
break;
}
case "cb_enableTIFFtoXML":
{
if (status)
{
EnableCIP3toTIFFWatcher(status);
EnableTIFFtoXMLWatcher(status);
CountDown();
}
else
{
//If the user disables the conversion, it will just dispose objects.
TIFFSubscription.Dispose();
CIP3Subscription.Dispose();
timer1.Stop();
}
break;
}
}
}
以下是您的代码应该更接近的版本:
IObservable<string> query =
from item in TIFFFiles // TIFFFiles = new Subject<string>()
let ColorSeparator = new ColorSeparatorDefiner(cmb_tiffSelectedIndex).Delimiter
let jobInfo = new CMYKJobInformationForDictionarySorting(currFile, ColorSeparator)
let file = jobInfo.ConventionName
from WriteDefaultXML in Observable.Start(() => new PPFConverter.writeFinalXml(item.Key, tb_TIFFtoXMLOutputFolder.Text))
from ImageListSorted in Observable.Start(() => ImageBuilder(item.Value, ColorSeparator))
from DPI in Observable.Start(() => new ObtainDPI(item.Value.ElementAt(0)))
from IZDataInfo in Observable.Start(() => new IZAreaDataInfo(izAreaSettings.FrmIZArea_numberOfZones, izAreaSettings.FrmIZArea_zoneWidth, izAreaSettings.FrmIZArea_firstZoneWidth, izAreaSettings.FrmIZArea_lastZoneWidth, izAreaSettings.FrmIZArea_zoneAreaWidth, izAreaSettings.FrmIZArea_zoneAreaHeight, DPI.DPI))
from RotateCMYK in Observable.Start(() => Rotate(ImageListSorted.CMYKmages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageRotationCount))
from RotateImposition in Observable.Start(() => Rotate(ImageListSorted.ImposedImages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageRotationCount))
from IZDraw in Observable.Start(() => InkZoneAreaImage(IZDataInfo.IzArea_ZoneAreaWidth, IZDataInfo.IzArea_ZoneAreaHeight))
from CMYKIZCalculation in Observable.Start(() => LevelCalc(IZDataInfo.IzArea_ZoneWidth, DPI.DPI, RotateCMYK.RotatedImgs, IZDraw.ZoneImage, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont))
from ImposedIZCalculation in Observable.Start(() => LevelCalc(IZDataInfo.IzArea_ZoneWidth, DPI.DPI, RotateImposition.RotatedImgs, IZDraw.ZoneImage, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont))
from CMYKResize in Observable.Start(() => ResizeCollection(RotateCMYK.RotatedImgs, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewWidth, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewHeight))
from ImpositionResize in Observable.Start(() => ResizeCollection(RotateImposition.RotatedImgs, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewWidth, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewHeight))
from CombineTHumbnail in Observable.Start(() => CombineImages(CMYKResize.ResizedImages, (bool)Properties.Settings.Default["TIFFtoXML_NegateImage"]))
from CreateComposedImage in Observable.Start(() => new SpotImageComposer(CombineTHumbnail.FinalCombinedImage, ImpositionResize.ResizedImages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont, ColorSeparator, tiffToXmlpngPreviewSettings.TIffToXml_UnknownSpotcolorHandling))
from FinalXMLWrite in Observable.Start(() => new WriteXMLData(WriteDefaultXML.finalXmlName, WriteDefaultXML.OutputFolder, CMYKIZCalculation, ImposedIZCalculation, CreateComposedImage.FinalImage, WriteDefaultXML.xmlDoc, InfoFromFiles, ColorSeparator, item.Value))
select file;
_subscription =
query
.Subscribe(f =>
{
if ((bool)Properties.Settings.Default["TIFFtoXML_DeleteInput"])
{
System.IO.File.Delete(f); //Wanted to delete the files
}
}, () =>
{
/* code to execute when observable finishes */
/* You must call `TIFFFiles.OnCompleted()` */
});
请不要使用任何计时器,线程或任务。如果您确实说出了原因,我可以帮助您根据需要进行修复。
当您致电:TIFFFiles.OnNext(filename);
时,所有这些都会被触发。
这是观察文件系统的代码,然后根据没有添加其他文件的TimeSpan.FromSeconds(30.0)
将更改分组在一起:
IObservable<FileSystemEventArgs> filesCreated =
Observable
.Using(
() =>
{
var fsw = new FileSystemWatcher(@"C:\Users\james\Temporary\Testing");
fsw.EnableRaisingEvents = true;
return fsw;
},
fsw => Observable.FromEventPattern
<FileSystemEventHandler, FileSystemEventArgs>(
h => fsw.Created += h,
h => fsw.Created -= h))
.Delay(TimeSpan.FromSeconds(0.1))
.Select(x => x.EventArgs);
IObservable<FileSystemEventArgs[]> batchesOfFilesCreated =
filesCreated
.Publish(fc =>
from w in fc.Window(() => fc.Throttle(TimeSpan.FromSeconds(30.0)))
from fcs in w.ToArray()
select fcs);
现在您的查询如下所示:
var ColorSeparator = new ColorSeparatorDefiner(cmb_tiffSelectedIndex).Delimiter;
var query =
from gfcs in batchesOfFilesCreated.GroupBy(x => new CMYKJobInformationForDictionarySorting(currFile, ColorSeparator).ConventionName)
let file = gfcs.Key
from gfc in gfcs
from WriteDefaultXML in Observable.Start(() => new PPFConverter.writeFinalXml(item.Key, tb_TIFFtoXMLOutputFolder.Text))
from ImageListSorted in Observable.Start(() => ImageBuilder(item.Value, ColorSeparator))
from DPI in Observable.Start(() => new ObtainDPI(item.Value.ElementAt(0)))
from IZDataInfo in Observable.Start(() => new IZAreaDataInfo(izAreaSettings.FrmIZArea_numberOfZones, izAreaSettings.FrmIZArea_zoneWidth, izAreaSettings.FrmIZArea_firstZoneWidth, izAreaSettings.FrmIZArea_lastZoneWidth, izAreaSettings.FrmIZArea_zoneAreaWidth, izAreaSettings.FrmIZArea_zoneAreaHeight, DPI.DPI))
from RotateCMYK in Observable.Start(() => Rotate(ImageListSorted.CMYKmages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageRotationCount))
from RotateImposition in Observable.Start(() => Rotate(ImageListSorted.ImposedImages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageRotationCount))
from IZDraw in Observable.Start(() => InkZoneAreaImage(IZDataInfo.IzArea_ZoneAreaWidth, IZDataInfo.IzArea_ZoneAreaHeight))
from CMYKIZCalculation in Observable.Start(() => LevelCalc(IZDataInfo.IzArea_ZoneWidth, DPI.DPI, RotateCMYK.RotatedImgs, IZDraw.ZoneImage, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont))
from ImposedIZCalculation in Observable.Start(() => LevelCalc(IZDataInfo.IzArea_ZoneWidth, DPI.DPI, RotateImposition.RotatedImgs, IZDraw.ZoneImage, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont))
from CMYKResize in Observable.Start(() => ResizeCollection(RotateCMYK.RotatedImgs, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewWidth, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewHeight))
from ImpositionResize in Observable.Start(() => ResizeCollection(RotateImposition.RotatedImgs, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewWidth, tiffToXmlpngPreviewSettings.FrmTiffPng_imagePreviewHeight))
from CombineTHumbnail in Observable.Start(() => CombineImages(CMYKResize.ResizedImages, (bool)Properties.Settings.Default["TIFFtoXML_NegateImage"]))
from CreateComposedImage in Observable.Start(() => new SpotImageComposer(CombineTHumbnail.FinalCombinedImage, ImpositionResize.ResizedImages, tiffToXmlpngPreviewSettings.FrmTiffPng_imageOrientationCont, ColorSeparator, tiffToXmlpngPreviewSettings.TIffToXml_UnknownSpotcolorHandling))
from FinalXMLWrite in Observable.Start(() => new WriteXMLData(WriteDefaultXML.finalXmlName, WriteDefaultXML.OutputFolder, CMYKIZCalculation, ImposedIZCalculation, CreateComposedImage.FinalImage, WriteDefaultXML.xmlDoc, InfoFromFiles, ColorSeparator, item.Value))
select file;
_subscription =
query
.Subscribe(f =>
{
if ((bool)Properties.Settings.Default["TIFFtoXML_DeleteInput"])
{
System.IO.File.Delete(f); //Wanted to delete the files
}
}, () =>
{
/* code to execute when observable finishes */
/* You must call `TIFFFiles.OnCompleted()` */
});
注意:这消除了代码中的计时器和线程的使用。您应该能够将其设置一次并使其保持运行状态。只要记得在你希望它停止运行时调用_subscription.Dispose()
。
更新:我编辑了包括我所做的一切的最终代码=)!它最终工作,现在我只是设置一些细节(更多关于业务逻辑和工作流程)。我知道这远远不是好事,但就目前我决定要做的事情而言。
我的下一个目标是对所有类型的文件进行单一订阅,并处理查询本身的不同情况;它会使事情变得更容易,并允许我用更少的代码做同样的事情。并提前感谢您的帮助。这就像是对我的Reactive Extensions的介绍嘿,我开始阅读和挖掘它。
public partial class Form1 : AsyncBaseDialog
{
private IDisposable CIP3Subscription = null;
static System.Windows.Forms.Timer timer1; //The timer is used but just for visual purposes - nothing is related to him
IObservable<FileSystemEventArgs> TIFFFilesCreated;
IObservable<FileSystemEventArgs[]> TIFFGroupFiles;
IObservable<FileSystemEventArgs> CIP3FilesCreated;
IObservable<FileSystemEventArgs[]> CIP3GroupFiles;
bool currStatus = (bool)Properties.Settings.Default["TIFFtoXML_EnabledConversion"]; //If the enable conversion checkbox is enabled, fire the observable
if(currStatus)
{
EnableTIFFtoXMLWatcher(currStatus);
EnableCIP3toTIFFWatcher(currStatus);
}
timer1 = new System.Windows.Forms.Timer();
timer1.Tick += new EventHandler(SecondElapsed);
timer1.Enabled = currStatus;
counter = Convert.ToInt32(Properties.Settings.Default.TIFFtoXML_MainTimer);
}
#region timerStuff
DateTime start;
double s;
private void CountDown()
{
start = DateTime.Now;
s = (double)counter;
timer1.Start();
}
private void SecondElapsed(object sender, EventArgs e)
{
double remainingSeconds = s - (DateTime.Now - start).TotalSeconds;
if (remainingSeconds <= 0)
{
timer1.Stop();
timer1.Interval = (int)counter;
timer1.Start();
CountDown();
}
var x = TimeSpan.FromSeconds(remainingSeconds);
tb_MainTimer.Text = x.Seconds.ToString();
}
#endregion
#region ObservableMethods //Methods i built in order to handle the observable behaviour
private IObservable<FileSystemEventArgs[]> CreateObjectForConvertAll(string inputFolder, string extension)
{
//I've a checkbox where the user selects "Convert all", and it will convert everything in the folder. Since i didn't wanted to repeat
//code by calling all methods again, this method returns me an object i can query
List<FileSystemEventArgs> tempList = new List<FileSystemEventArgs>(Directory.GetFiles(tb_TIFFtoXMLInputFolder.Text, extension, SearchOption.TopDirectoryOnly).ToList()
.Select(x => new FileSystemEventArgs(WatcherChangeTypes.Created, "", x)));
List<FileSystemEventArgs[]> fswArgsArrayList = new List<FileSystemEventArgs[]>();
fswArgsArrayList.Add(tempList.ToArray());
var finalObservable = fswArgsArrayList.ToArray();
var finalObservableNotArray = finalObservable.ToArray().ToObservable();
return finalObservableNotArray;
}
private IObservable<FileSystemEventArgs> CreateReactiveFSWInstance(string inputFolder, string fileFilter, bool checkBoxStatus)
{
//Creates the Reactive FSW instance
//checkBoxStatus => Enabled or not ; if the user enables the conversion, EnableRaisingEvents will be true
IObservable<FileSystemEventArgs> filesCreated =
Observable
.Using(
() =>
{
var fsw = new FileSystemWatcher(inputFolder)
{
EnableRaisingEvents = checkBoxStatus,
Filter = fileFilter
};
return fsw;
},
fsw => Observable.FromEventPattern
<FileSystemEventHandler, FileSystemEventArgs>(
h => fsw.Created += h,
h => fsw.Created -= h))
.Delay(TimeSpan.FromSeconds(0.1))
.Select(x => x.EventArgs);
return filesCreated;
}
private IObservable<FileSystemEventArgs[]> TIFFPublish(IObservable<FileSystemEventArgs> observable)
{
var GroupFiles =
observable
.Publish(fc =>
from w in fc.Window(() => fc.Throttle(TimeSpan.FromSeconds((double)counter)))
from fcs in w.ToArray()
select fcs);
return GroupFiles;
}
#endregion
private void StartCIP3ProcessingQuery(IObservable<FileSystemEventArgs[]> Files)
{
//query goes here...
}
private void StartTIFFProcessingQuery(IObservable<FileSystemEventArgs[]> Files)
{
//query goes here...
}
private void EnableTIFFtoXMLWatcher(bool status)
{
//Enable the reactive watcher for TIF files
TIFFFilesCreated = CreateReactiveFSWInstance(tb_TIFFtoXMLInputFolder.Text, "*.tif", status);
TIFFGroupFiles = TIFFPublish(TIFFFilesCreated);
StartTIFFProcessingQuery(TIFFGroupFiles);
}
private void EnableCIP3toTIFFWatcher(bool status)
{
//Enable the reactive watcher for CIP3 files
CIP3FilesCreated = CreateReactiveFSWInstance(tb_TIFFtoXMLInputFolder.Text, "*.*", status);
CIP3GroupFiles = TIFFPublish(CIP3FilesCreated);
StartCIP3ProcessingQuery(CIP3GroupFiles, false);
}
private void SubscriptionDisposal()
{
//Disposal methods
TIFFSubscription.Dispose();
CIP3Subscription.Dispose();
}
//Enable or disable the conversio, or convert all
private void CheckboxChangedEventHandler(object sender, EventArgs e)
{
CheckBox CurrChk = sender as CheckBox;
bool status = CurrChk.Checked;
switch (CurrChk.Name)
{
case "TIFFtoXML_chkConvertAll":
{
if(status)
{
cb_enableTIFFtoXML.Checked = true; //Enabling this checkbox triggers the other case and fires the FSW
var convertAllTIFFObj = CreateObjectForConvertAll(tb_TIFFtoXMLInputFolder.Text, "*.tif");
StartTIFFProcessingQuery(convertAllTIFFObj);
var convertAllCIP3Obj = CreateObjectForConvertAll(tb_TIFFtoXMLInputFolder.Text, "*.*");
StartCIP3ProcessingQuery(convertAllCIP3Obj,true);
CurrChk.Checked = false;
}
break;
}
case "cb_enableTIFFtoXML":
{
if (status)
{
EnableCIP3toTIFFWatcher(status);
EnableTIFFtoXMLWatcher(status);
CountDown();
}
else
{
//If the user disables the conversion, it will just dispose objects.
TIFFSubscription.Dispose();
CIP3Subscription.Dispose();
timer1.Stop();
}
break;
}
}
}