using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Image;
using Image.Core;
using ImageMagick;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace ConsoleInterface
{
///
/// TaskExecutor is a helper class for executing tasks in parallel.
///
public class TaskExecutor
{
public static ILogger Logger = NullLogger.Instance;
private readonly TaskExecutorOptions _options;
///
/// Creates a new instance of TaskExecutor.
///
/// The TaskExecutor options.
/// Raised when the options are null.
private TaskExecutor(TaskExecutorOptions options)
{
_options = options ?? throw new ArgumentException("Options cannot be null!");
}
///
/// Creates a new instance of TaskExecutor by calling the private constructor.
///
/// The TaskExecutor options.
public static TaskExecutor Create(TaskExecutorOptions options)
{
return new TaskExecutor(options);
}
///
/// Cleans an image. Errors are silenced by default.
///
/// The file path of the image to be cleaned.
/// The output sink for the image..
/// True of the image was cleaned, false otherwise.
public bool CleanImage(string filePath, IOutputSink outputSink)
{
try
{
Logger.LogDebug(
$"Cleaning {filePath}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.OutputSink)}.");
ICompressor compressor = NullCompressor.Instance;
if (_options.EnableCompression)
{
compressor = LosslessCompressor.Instance;
}
var imageMagick = new MagickImage(filePath);
IMetadataRemover metadataRemover = new ExifRemoverAndCompressor(imageMagick, compressor);
return outputSink.Save(metadataRemover);
}
catch (Exception e)
{
Logger.LogError(e.ToString());
return false;
}
}
///
/// Cleans images in parallel using the built in Task Parallel Library.
///
/// An enumerable of file names.
public void ParallelCleanImages(IEnumerable fileNames)
{
Logger.LogInformation("Starting parallel image cleaning.");
var filenamesArray = fileNames as string[] ?? fileNames.ToArray();
if (!filenamesArray.Any())
{
Logger.LogWarning("Empty fileNames, nothing to do.");
return;
}
var tasks = new List>();
foreach (var fileName in filenamesArray)
{
var task = new Task(() => CleanImage(fileName, _options.OutputSink));
tasks.Add(task);
task.Start();
}
var result = Task.WhenAll(tasks);
result.Wait();
var successTasks = tasks.Count(t => t.IsCompleted && t.Result);
var errorTasks = tasks.Count - successTasks;
Logger.LogInformation($"All tasks completed. Success: {successTasks}, Failures: {errorTasks}");
}
}
}