/// <summary> /// Run a variation of the pipeline that uses a user-specified number of tasks for the filter stage. /// </summary> /// <param name="fileNames">List of image file names in source directory</param> /// <param name="sourceDir">Name of directory of source images</param> /// <param name="queueLength">Length of image queue</param> /// <param name="displayFn">Display action</param> /// <param name="cts">Cancellation token</param> /// <param name="filterTaskCount">Number of filter tasks</param> static void RunLoadBalancedPipeline(IEnumerable <string> fileNames, string sourceDir, int queueLength, Action <ImageInfo> displayFn, CancellationTokenSource cts, int filterTaskCount) { // Create data pipes var originalImages = new BlockingCollection <ImageInfo>(queueLength); var thumbnailImages = new BlockingCollection <ImageInfo>(queueLength); var filteredImageMultiplexer = new BlockingMultiplexer <ImageInfo>(info => info.SequenceNumber, 0, queueLength); var filteredImagesCollections = (BlockingCollection <ImageInfo>[])Array.CreateInstance( typeof(BlockingCollection <ImageInfo>), filterTaskCount); try { // Start pipelined tasks Action <ImageInfo> updateStatisticsFn = info => { info.QueueCount1 = originalImages.Count(); info.QueueCount2 = thumbnailImages.Count(); info.QueueCount3 = filteredImageMultiplexer.Count; }; const TaskCreationOptions options = TaskCreationOptions.LongRunning; var f = new TaskFactory(CancellationToken.None, options, TaskContinuationOptions.None, TaskScheduler.Default); Task[] tasks = (Task[])Array.CreateInstance(typeof(Task), filterTaskCount + 3); int taskId = 0; tasks[taskId++] = f.StartNew(() => LoadPipelinedImages(fileNames, sourceDir, originalImages, cts)); tasks[taskId++] = f.StartNew(() => ScalePipelinedImages(originalImages, thumbnailImages, cts)); for (int i = 0; i < filterTaskCount; i++) { var tmp = i; filteredImagesCollections[tmp] = filteredImageMultiplexer.GetProducerQueue(); tasks[taskId++] = f.StartNew(() => FilterPipelinedImages(thumbnailImages, filteredImagesCollections[tmp], cts)); } tasks[taskId++] = f.StartNew(() => DisplayPipelinedImages(filteredImageMultiplexer.GetConsumingEnumerable(), displayFn, updateStatisticsFn, cts)); Task.WaitAll(tasks); } finally { // there might be cleanup in the case of cancellation or an exception. DisposeImagesInQueue(originalImages); DisposeImagesInQueue(thumbnailImages); foreach (var filteredImages in filteredImagesCollections) { DisposeImagesInQueue(filteredImages); } foreach (var info in filteredImageMultiplexer.GetCleanupEnumerable()) { info.Dispose(); } } }
/// <summary> /// Run a pipeline that uses a user-specified number of tasks for the filter stage. /// </summary> /// <param name="fileNames">List of image file names in source directory</param> /// <param name="sourceDir">Name of directory of source images</param> /// <param name="queueLength">Length of image queue</param> /// <param name="cts">Cancellation token</param> /// <param name="filterTaskCount">Number of filter tasks</param> public static void RunPipeline(IEnumerable <string> fileNames, string sourceDir, int queueLength, CancellationTokenSource token, int filterTaskCount) { using (CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(token.Token)) { // Create data pipes var originalImages = new BlockingCollection <ImageInfo>(queueLength); var thumbnailImages = new BlockingCollection <ImageInfo>(queueLength); var filteredImageMultiplexer = new BlockingMultiplexer <ImageInfo>(info => info.SequenceNumber, 0, queueLength); var filteredImagesCollections = (BlockingCollection <ImageInfo>[])Array.CreateInstance( typeof(BlockingCollection <ImageInfo>), filterTaskCount); try { const TaskCreationOptions options = TaskCreationOptions.LongRunning; var factory = new TaskFactory(CancellationToken.None, options, TaskContinuationOptions.None, TaskScheduler.Default); Task[] tasks = (Task[])Array.CreateInstance(typeof(Task), filterTaskCount + 3); int taskId = 0; tasks[taskId++] = factory.StartNew(() => PipelinePhases.LoadPipelinedImages(fileNames, sourceDir, originalImages, cts)); tasks[taskId++] = factory.StartNew(() => PipelinePhases.ScalePipelinedImages(originalImages, thumbnailImages, cts)); for (int i = 0; i < filterTaskCount; i++) { var tmp = i; filteredImagesCollections[tmp] = filteredImageMultiplexer.GetProducerQueue(); tasks[taskId++] = factory.StartNew(() => PipelinePhases.FilterPipelinedImages(thumbnailImages, filteredImagesCollections[tmp], cts)); } tasks[taskId++] = factory.StartNew(() => PipelinePhases.SavePipelinedImages(filteredImageMultiplexer.GetConsumingEnumerable(), cts)); Task.WaitAll(tasks); } finally { // there might be cleanup in the case of cancellation or an exception. DisposeImagesInQueue(originalImages); DisposeImagesInQueue(thumbnailImages); foreach (var filteredImages in filteredImagesCollections) { DisposeImagesInQueue(filteredImages); } foreach (var info in filteredImageMultiplexer.GetCleanupEnumerable()) { info.Dispose(); } } } }
/// <summary> /// Run a variation of the pipeline that uses a user-specified number of tasks for the filter stage. /// </summary> /// <param name="fileNames">List of image file names in source directory</param> /// <param name="sourceDir">Name of directory of source images</param> /// <param name="queueLength">Length of image queue</param> /// <param name="displayFn">Display action</param> /// <param name="cts">Cancellation token</param> /// <param name="filterTaskCount">Number of filter tasks</param> static void RunLoadBalancedPipeline(IEnumerable<string> fileNames, string sourceDir, int queueLength, Action<ImageInfo> displayFn, CancellationTokenSource cts, int filterTaskCount) { // Create data pipes var originalImages = new BlockingCollection<ImageInfo>(queueLength); var thumbnailImages = new BlockingCollection<ImageInfo>(queueLength); var filteredImageMultiplexer = new BlockingMultiplexer<ImageInfo>(info => info.SequenceNumber, 0, queueLength); var filteredImagesCollections = (BlockingCollection<ImageInfo>[])Array.CreateInstance( typeof(BlockingCollection<ImageInfo>), filterTaskCount); try { // Start pipelined tasks Action<ImageInfo> updateStatisticsFn = info => { info.QueueCount1 = originalImages.Count(); info.QueueCount2 = thumbnailImages.Count(); info.QueueCount3 = filteredImageMultiplexer.Count; }; const TaskCreationOptions options = TaskCreationOptions.LongRunning; var f = new TaskFactory(CancellationToken.None, options, TaskContinuationOptions.None, TaskScheduler.Default); Task[] tasks = (Task[])Array.CreateInstance(typeof(Task), filterTaskCount + 3); int taskId = 0; tasks[taskId++] = f.StartNew(() => LoadPipelinedImages(fileNames, sourceDir, originalImages, cts)); tasks[taskId++] = f.StartNew(() => ScalePipelinedImages(originalImages, thumbnailImages, cts)); for (int i = 0; i < filterTaskCount; i++) { var tmp = i; filteredImagesCollections[tmp] = filteredImageMultiplexer.GetProducerQueue(); tasks[taskId++] = f.StartNew(() => FilterPipelinedImages(thumbnailImages, filteredImagesCollections[tmp], cts)); } tasks[taskId++] = f.StartNew(() => DisplayPipelinedImages(filteredImageMultiplexer.GetConsumingEnumerable(), displayFn, updateStatisticsFn, cts)); Task.WaitAll(tasks); } finally { // there might be cleanup in the case of cancellation or an exception. DisposeImagesInQueue(originalImages); DisposeImagesInQueue(thumbnailImages); foreach (var filteredImages in filteredImagesCollections) DisposeImagesInQueue(filteredImages); foreach (var info in filteredImageMultiplexer.GetCleanupEnumerable()) info.Dispose(); } }