ImgMetadataRemover/ConsoleInterface/TaskExecutor.cs

100 lines
3.7 KiB
C#
Raw Normal View History

2022-01-23 13:12:17 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
2022-04-02 14:22:42 +00:00
using Image;
using Image.Core;
2022-01-23 13:12:17 +00:00
using ImageMagick;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
2022-04-02 14:22:42 +00:00
namespace ConsoleInterface
2022-01-23 13:12:17 +00:00
{
2022-01-23 17:30:05 +00:00
/// <summary>
/// TaskExecutor is a helper class for executing tasks in parallel.
/// </summary>
2022-01-23 13:12:17 +00:00
public class TaskExecutor
{
public static ILogger Logger = NullLogger.Instance;
private readonly TaskExecutorOptions _options;
2022-01-23 17:30:05 +00:00
/// <summary>
/// Creates a new instance of TaskExecutor.
/// </summary>
/// <param name="options">The TaskExecutor options.</param>
/// <exception cref="ArgumentException">Raised when the options are null.</exception>
2022-01-23 13:12:17 +00:00
private TaskExecutor(TaskExecutorOptions options)
{
_options = options ?? throw new ArgumentException("Options cannot be null!");
}
2022-01-23 17:30:05 +00:00
/// <summary>
/// Creates a new instance of TaskExecutor by calling the private constructor.
/// </summary>
/// <param name="options">The TaskExecutor options.</param>
2022-01-23 13:12:17 +00:00
public static TaskExecutor Create(TaskExecutorOptions options)
{
return new TaskExecutor(options);
}
2022-01-23 17:30:05 +00:00
/// <summary>
/// Cleans an image. Errors are silenced by default.
/// </summary>
/// <param name="filePath">The file path of the image to be cleaned.</param>
/// <param name="outputSink">The output sink for the image..</param>
2022-01-23 17:30:05 +00:00
/// <returns>True of the image was cleaned, false otherwise.</returns>
public bool CleanImage(string filePath, IOutputSink outputSink)
2022-01-23 13:12:17 +00:00
{
try
{
2022-04-02 14:22:42 +00:00
Logger.LogDebug(
$"Cleaning {filePath}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.OutputSink)}.");
2022-01-23 13:12:17 +00:00
ICompressor compressor = NullCompressor.Instance;
2022-04-02 14:33:48 +00:00
if (_options.EnableCompression)
{
compressor = LosslessCompressor.Instance;
}
var imageMagick = new MagickImage(filePath);
2022-02-12 20:12:57 +00:00
IMetadataRemover metadataRemover = new ExifRemoverAndCompressor(imageMagick, compressor);
return outputSink.Save(metadataRemover);
2022-01-23 13:12:17 +00:00
}
catch (Exception e)
{
Logger.LogError(e.ToString());
return false;
}
}
2022-01-23 17:30:05 +00:00
/// <summary>
/// Cleans images in parallel using the built in Task Parallel Library.
/// </summary>
/// <param name="fileNames">An enumerable of file names.</param>
2022-01-23 13:12:17 +00:00
public void ParallelCleanImages(IEnumerable<string> 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<Task<bool>>();
foreach (var fileName in filenamesArray)
{
var task = new Task<bool>(() => CleanImage(fileName, _options.OutputSink));
2022-01-23 13:12:17 +00:00
tasks.Add(task);
task.Start();
}
var result = Task.WhenAll(tasks);
result.Wait();
var successTasks = tasks.Count(t => t.IsCompleted && t.Result);
2022-01-27 21:22:10 +00:00
var errorTasks = tasks.Count - successTasks;
Logger.LogInformation($"All tasks completed. Success: {successTasks}, Failures: {errorTasks}");
2022-01-23 13:12:17 +00:00
}
}
}