public void ScanFolder(string path, string[] fileExtensions, bool includeSubdirectories = true, bool clearDatabase = false, bool resetDatabase = false) { ScanComplete = false; ScanStart = DateTime.Now; MySQLContext databaseContext = null; LastScan = DateTime.Parse("1/1/1990"); DirectoriesProcessed = 0; DirectoriesSkipped = 0; FilesProcessed = 0; FilesSkipped = 0; try { if (Directory.Exists(path)) { if (resetDatabase) { Logger.Info("Resetting database..."); using (MySQLContext db = new MySQLContext(Logger)) { db.DropTablesIfExist(); } Globals.TablesChecked = false; } else if (clearDatabase) { Logger.Info("Clearing database..."); using (MySQLContext db = new MySQLContext(Logger)) { db.MediaFiles.Clear(); db.Albums.Clear(); db.Scans.Clear(); db.SaveChanges(); } } Logger.Info("Getting last scan date..."); using (MySQLContext db = new MySQLContext(Logger)) { if (db.Scans.Any(s => s.FolderPath == path)) { LastScan = db.Scans.Where(s => s.FolderPath == path).Select(s => s.LastScanned).Max(); } try { var scanData = new Repository.Scan(Logger, path); scanData.AddOrUpdate(); } catch (Exception scanEx) { Logger.Fatal($"There was an error updating the last scan information. Error: {scanEx.Message}", scanEx); } } Logger.Info("Beginning loading directories..."); ScanDirectory(path, fileExtensions, includeSubdirectories); Logger.Info($"Loaded {ScanActions.Count()} files and directories."); Logger.Info("Beginning scanning files and directories."); while (ScanActionsRetry.Any() || ScanActions.Any()) { if (!string.IsNullOrEmpty(ParallelThreads)) { Logger.Info($"Running with maximum number of threads: {ParallelThreads}."); var scanOptions = new ParallelOptions { MaxDegreeOfParallelism = int.Parse(ParallelThreads) }; Parallel.Invoke(scanOptions, ScanActions.ToArray()); } else { Parallel.Invoke(ScanActions.ToArray()); } ScanActions.Clear(); if (ScanActionsRetry.Any()) { Logger.Info($"Processes to retry: {ScanActionsRetry.Count()}. Re-running errored processes."); ScanActions.Clear(); ScanActions.AddRange(ScanActionsRetry); ScanActionsRetry = new ConcurrentBag <Action>(); } } Logger.Info($"Scanned {FilesProcessed} files, skipped {FilesSkipped} files."); Logger.Info($"Scanned {DirectoriesProcessed} albums, skipped {DirectoriesSkipped} directories."); Logger.Info($"Encountered {Errors.Count} errors."); Logger.Info($"Cleaning up database..."); using (var db = new MySQLContext(Logger)) { foreach (var album in db.Albums.Where(a => a.LastScanned < LastScan)) { if (Directory.Exists(album.FolderPath)) { album.LastScanned = LastScan; } else { db.Albums.Remove(album); } } db.SaveChanges(); foreach (var mp3File in db.MediaFiles.Where(f => f.LastScanned < LastScan)) { if (File.Exists(mp3File.FilePath)) { mp3File.LastScanned = LastScan; } else { db.MediaFiles.Remove(mp3File); } } db.SaveChanges(); } foreach (var error in Errors) { Logger.Info($"File: {error.FilePath}; Error: {error.Details}"); } } else { throw new Exception($"Directory '{path}' does not exist."); } } catch (Exception ex) { Logger.Error($"Error scanning files: {path}", ex); Errors.Add(new FileError(ex, path, "Error scanning files.")); } ScanEnd = DateTime.Now; ScanComplete = true; if (databaseContext != null) { try { databaseContext.Dispose(); } catch { } finally { databaseContext = null; } } }