ImgMetadataRemover/ImageCore/Tasks/TaskExecutor.cs

104 lines
3.9 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;
using Image.Core;
using Image.Files;
2022-01-23 13:12:17 +00:00
using ImageMagick;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Image.Tasks
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="newFilePath">The new file path of the cleaned 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, string newFilePath)
2022-01-23 13:12:17 +00:00
{
try
{
var fileExists = FileSystemHelpers.CheckIfFileExists(newFilePath);
if (fileExists)
{
Logger.LogWarning($"File {newFilePath} exists, skipping");
return false;
}
2022-01-23 13:12:17 +00:00
ICompressor compressor = NullCompressor.Instance;
var imageMagick = new MagickImage(filePath);
2022-01-23 17:30:05 +00:00
if (_options.EnableCompression) compressor = LosslessCompressor.Instance;
2022-01-23 13:12:17 +00:00
Logger.LogDebug(
2022-02-12 20:12:57 +00:00
$"Cleaning {filePath}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.OutputSink)}.");
IMetadataRemover metadataRemover = new ExifRemoverAndCompressor(imageMagick, compressor);
metadataRemover.CleanImage(newFilePath);
2022-01-23 13:12:17 +00:00
return true;
}
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>(() =>
2022-02-12 20:12:57 +00:00
CleanImage(fileName, _options.OutputSink.GetOutputPath(fileName)));
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
}
}
}