using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Dasync.Collections; using Microsoft.Extensions.Logging; namespace MaddoShared { public class ImageCreationStuff(ILogger logger, PicSettings picSettings, ImageCreatorSharp imageCreatorService) { public class Options { public bool AggiornaSottodirectory { get; set; } public bool CreaSottocartelle { get; set; } public int FilePerCartella { get; set; } public string SuffissoCartelle { get; set; } public int CifreContatore { get; set; } public NumerazioneType NumerazioneType { get; set; } public string SourcePath { get; set; } public string DestinationPath { get; set; } public int MaxThreads { get; set; } public int ChunksSize { get; set; } public bool LinearExecution { get; set; } } public async Task CreaCatalogoParallel(Options options, ConcurrentBag results, EventHandler> updateEvent, CancellationToken cancellationToken = default(CancellationToken)) { var stopwatch = new Stopwatch(); stopwatch.Start(); // todo immagini counter //todo set label await ProcessImagesParallel(options, results, updateEvent, cancellationToken); // todo set finito label stopwatch.Stop(); return $"{stopwatch.Elapsed.Hours}h {stopwatch.Elapsed.Minutes}m ${stopwatch.Elapsed.Seconds}s ({stopwatch.Elapsed.TotalSeconds}s)"; } public async Task ProcessImagesParallel( Options options, ConcurrentBag results, EventHandler> updateEvent, CancellationToken cancellationToken = default) { List dataToProcess = GetFilesToProcess(options); // int threads = options.MaxThreads == 0 ? Environment.ProcessorCount * 2 : options.MaxThreads; int threads = options.MaxThreads; Bitmap logoBmp = null; // Load Logo if (picSettings.LogoAggiungi & File.Exists(picSettings.LogoNomeFile)) { logoBmp = new Bitmap(picSettings.LogoNomeFile); } Func processFile = async fileData => { using var logoCopy = logoBmp.Clone(new Rectangle(0, 0, logoBmp.Width, logoBmp.Height), logoBmp.PixelFormat); var imgState = new ImageState { WorkFile = fileData.File, DestDir = fileData.Directory, }; await imageCreatorService.CreaImmagineThread(imgState, logoCopy); // using var imgCreator = new ImageCreatorSharp(fileData.File, fileData.Directory, picSettings); // await imgCreator.CreaImmagineThread(fileData.File.Name, logoCopy); results.Add(fileData.File.Name); try { updateEvent?.Invoke(this, new Tuple(fileData.File.Name, dataToProcess.Count)); } catch (Exception e) { logger.LogError(e, "Error in reporting update"); throw; } // finally // { // imgCreator = null; // } }; if (options.LinearExecution) { foreach (var fileData in dataToProcess) await processFile(fileData); } else { var chunks = options.ChunksSize > 0 ? SplitList(dataToProcess, options.ChunksSize) : new List> { dataToProcess }; foreach (var chunk in chunks) { await chunk.ParallelForEachAsync( processFile, maxDegreeOfParallelism: threads, false, cancellationToken); chunk.Clear(); GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: false, compacting: false); } } try { logoBmp?.Dispose(); } catch (Exception e) { logger.LogError(e, "Error in disposing the logo"); } } private List GetFilesToProcess(Options options) { if (options.AggiornaSottodirectory && options.CreaSottocartelle) { var helper = new FileHelperSharp(); return helper.GetFilesRecursive( new DirectoryInfo(options.SourcePath), new DirectoryInfo(options.DestinationPath), "*.jpg", new FileHelperOptions { FilesPerFolder = options.FilePerCartella, Suffix = options.SuffissoCartelle, CounterSize = options.CifreContatore, NumerationType = options.NumerazioneType }); } var files = Directory.EnumerateFiles( options.SourcePath, "*.jpg", options.AggiornaSottodirectory ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); return files.Select(x => { var fInfo = new FileInfo(x); var filePath = fInfo.DirectoryName; var trimmedSourcePath = options.SourcePath.TrimEnd('\\'); var newFilePath = fInfo.FullName.Replace(trimmedSourcePath, "").TrimStart('\\'); newFilePath = Path.Combine(options.DestinationPath, newFilePath); var destFolderPath = new FileInfo(newFilePath).DirectoryName; var destFolderInfo = new DirectoryInfo(destFolderPath); destFolderInfo.EnsureDirectoryExists(); return new FileData(fInfo, new DirectoryInfo(new FileInfo(newFilePath).DirectoryName)); // var destDir = new FileInfo(newFilePath).Directory!; // destDir.Create(); // Ensure exists // // return new FileData(fInfo, destDir); }).ToList(); } // public async Task CreaImmaginiParallel(Options options, ConcurrentBag results, // EventHandler> updateEvent, // CancellationToken cancellationToken = default(CancellationToken)) // { // var dataToProcess = new List(); // if (options.AggiornaSottodirectory && options.CreaSottocartelle) // { // var helper = new FileHelperSharp(); // dataToProcess = helper.GetFilesRecursive(new DirectoryInfo(options.SourcePath), // new DirectoryInfo(options.DestinationPath), // "*.jpg", new FileHelperOptions() // { // FilesPerFolder = options.FilePerCartella, // Suffix = options.SuffissoCartelle, // CounterSize = options.CifreContatore, // NumerationType = options.NumerazioneType // }); // } // else if (!options.CreaSottocartelle) // { // var files = Directory.EnumerateFiles(options.SourcePath, "*.jpg", // options.AggiornaSottodirectory // ? SearchOption.AllDirectories // : SearchOption.TopDirectoryOnly); // // dataToProcess = files.Select(x => // { // var fInfo = new FileInfo(x); // var filePath = fInfo.DirectoryName; // var trimmedSourcePath = options.SourcePath.TrimEnd('\\'); // var newFilePath = fInfo.FullName.Replace(trimmedSourcePath, "").TrimStart('\\'); // newFilePath = Path.Combine(options.DestinationPath, newFilePath); // // var destFolderPath = new FileInfo(newFilePath).DirectoryName; // var destFolderInfo = new DirectoryInfo(destFolderPath); // destFolderInfo.EnsureDirectoryExists(); // // return new FileData(fInfo, new DirectoryInfo(new FileInfo(newFilePath).DirectoryName)); // }).ToList(); // // //// TODO // //dataToProcess = // // (from f in Directory.EnumerateFiles(options.SourcePath, "*.jpg", // // options.AggiornaSottodirectory // // ? SearchOption.AllDirectories // // : SearchOption.TopDirectoryOnly) // // select new FileData(new FileInfo(f), // // new DirectoryInfo(options.DestinationPath.PathCombine( // // new FileInfo(f).DirectoryName.Replace(options.SourcePath.TrimEnd(new char[] {'\\'}), "") // // ) // // ) // // ) // // ) // // .ToList(); // } // // var threads = options.MaxThreads == 0 ? Environment.ProcessorCount * 2 : options.MaxThreads; // var scheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, threads) // .ConcurrentScheduler; // // //var allTasks = new List(); // var test = from d in dataToProcess // select Task.Factory.StartNew(async () => // { // var imgCreator = new ImageCreatorSharp(d.File, d.Directory); // await imgCreator.CreaImmagineThread(d.File.Name); // // //await new ImageCreatorSharp(d.File, d.Directory).CreaImmagineThread(d.File.Name); // // imgCreator = null; // // //var imgC = new ImageCreatorSharp(d.File, d.Directory); // //imgC.CreaImmagineThread(d.File.Name); // //imgC = null; // }, CancellationToken.None, TaskCreationOptions.None, scheduler); // // //int count = 0; // // if (options.LinearExecution) // { // foreach (var task in test) // { // await task; // } // } // else // { // if (options.ChunksSize == 0) // { // //var opts = new ParallelOptions() { MaxDegreeOfParallelism = threads, CancellationToken = cancellationToken, TaskScheduler = scheduler}; // await dataToProcess.ParallelForEachAsync(async fileData => // { // var imgCreator = new ImageCreatorSharp(fileData.File, fileData.Directory); // await imgCreator.CreaImmagineThread(fileData.File.Name); // // await new ImageCreatorSharp(fileData.File, fileData.Directory).CreaImmagineThread(fileData.File.Name); // results.Add(fileData.File.Name); // //count = Interlocked.Increment(ref count); // // try // { // updateEvent?.Invoke(this, new Tuple(fileData.File.Name, dataToProcess.Count)); // } // catch (Exception e) // { // logger.LogError(e, "Error in reporting update"); // //Console.WriteLine(e); // throw; // } // finally // { // // Disposing of the creator // imgCreator = null; // } // }, maxDegreeOfParallelism: threads, false, cancellationToken); // } // else // { // var asdf = SplitList(dataToProcess.ToList(), options.ChunksSize).ToList(); // // // foreach (var sdaf in asdf) // { // await sdaf.ParallelForEachAsync(async fileData => // { // var imgCreator = new ImageCreatorSharp(fileData.File, fileData.Directory); // await imgCreator.CreaImmagineThread(fileData.File.Name); // // await new ImageCreatorSharp(fileData.File, fileData.Directory).CreaImmagineThread( // // fileData.File.Name); // results.Add(fileData.File.Name); // //count = Interlocked.Increment(ref count); // try // { // updateEvent?.Invoke(this, // new Tuple(fileData.File.Name, dataToProcess.Count)); // } // catch (Exception e) // { // logger.LogError("Error in reporting update"); // //Console.WriteLine(e); // throw; // } // finally // { // imgCreator = null; // } // }, maxDegreeOfParallelism: threads, false, cancellationToken); // } // } // } // } public static IEnumerable> SplitList(List bigList, int nSize = 3) { for (int i = 0; i < bigList.Count; i += nSize) { yield return bigList.GetRange(i, Math.Min(nSize, bigList.Count - i)); } } } }