public static void ApplyNewTemplate(IList <FileInfo> movieFiles, List <TemplateItem> templates) { bool _genExtraThumb = FileManager.Configuration.Options.AutogenerateFolderJpg; bool _genThumb = FileManager.Configuration.Options.AutogenerateThumbnail; bool _updateRating = FileManager.Configuration.Options.UpdateIMDbRating; bool _genMainsheet = FileManager.Configuration.Options.AutogenerateMovieSheet; bool _genExtrasheet = FileManager.Configuration.Options.AutogenerateMoviesheetForFolder; bool _genParentFoldersheet = FileManager.Configuration.Options.AutogenerateMoviesheetForParentFolder; bool _genNfo = FileManager.Configuration.Options.AutogenerateMovieInfo; bool _doExports = (FileManager.Configuration.Options.ExportImagesOptions.AutoExportFanart1jpgAsBackground || FileManager.Configuration.Options.ExportImagesOptions.AutoExportFanart2jpgAsBackground || FileManager.Configuration.Options.ExportImagesOptions.AutoExportFanart3jpgAsBackground || FileManager.Configuration.Options.ExportImagesOptions.AutoExportFanartjpgAsBackground || FileManager.Configuration.Options.ExportImagesOptions.AutoExportFolderjpgAsCover) && FileManager.Configuration.Options.EnableExportFromMetadata; FileManager.CancellationPending = false; CancelProcessing.Reset(); // back up the setting and restore it at the end bool _autogenerateMetadata = FileManager.Configuration.Options.AutogenerateMoviesheetMetadata; UpdatesDispatcher _dispatcher = new UpdatesDispatcher(); try { FileManager.Configuration.Options.AutogenerateMoviesheetMetadata = false; /* * Main thread is dispatching work and ONLY rendering final result is passed to a thread * * Build first a list with "what needs to be done": what moviesheets need render, what foldersheets need render and what parentsheets need render * Then distribute rendering to threads */ int _total = movieFiles.Count; FileManager.ShowAdorner("Analyzing files... Please wait...", false); foreach (FileInfo _file in movieFiles) { MetadataUpdateItem _mui = null; try { // if we need to generate some item that requires main metadatafile if (_genMainsheet || _genExtrasheet || _genThumb || _genExtraThumb || _genNfo || _doExports) { // check if there is a metadata file available string _metadataFilename = FileManager.Configuration.GetMoviesheetMetadataPath(_file.FullName, false); if (!string.IsNullOrEmpty(_metadataFilename) && File.Exists(_metadataFilename)) { _mui = new MetadataUpdateItem(_file.FullName, _metadataFilename); _dispatcher.Add(_mui); // we have a candidate for thumbnail/extrathumbnail/moviesheet/extrasheet if (_genMainsheet) { UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.Moviesheet); _ui.Template = templates[0]; _mui.AddItem(_ui); } if (_genExtrasheet) { UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.Extrasheet); _ui.Template = templates[1]; _mui.AddItem(_ui); } if (_genThumb) { UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.Thumbnail); _mui.AddItem(_ui); } if (_genExtraThumb) { UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.ExtraThumbnail); _mui.AddItem(_ui); } if (_genNfo) { UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.Nfo); _mui.AddItem(_ui); } if (_doExports) { UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.ImagesExport); _mui.AddItem(_ui); } // generate the dummy file (if required) FileManager.GenerateDummyFile(_file.FullName); } } // if it is required to generate also sheet for parent folder if (FileManager.Configuration.Options.AutogenerateMoviesheetForParentFolder) { string _pfoldermetadataFilename = FileManager.Configuration.GetParentFolderMetadataPath(_file.FullName, false); if (!string.IsNullOrEmpty(_pfoldermetadataFilename) && File.Exists(_pfoldermetadataFilename)) { _mui = new MetadataUpdateItem(_file.FullName, _pfoldermetadataFilename); _dispatcher.Add(_mui); UpdateItem _ui = new UpdateItem(_file.FullName, UpdateItemType.ParentFoldersheet); _ui.Template = templates[2]; _mui.AddItem(_ui); } } } catch (Exception ex) { try { MovieItem _movieItem = FileManager.GetMovieByFilePath(_file.FullName); FileManager.SetMovieItemStatus(_movieItem, MovieItemStatus.Exception); Loggy.Logger.DebugException(string.Format("Processing file {0}", _file.FullName), ex); } catch { } } } // remove all Items from dispatcher that have no UpdateItems inside (Items.Count = 0) _dispatcher.RemoveEmptyItems(); // update status for movies that will not be processed (no metadata or nothing to do) foreach (FileInfo _file in movieFiles) { if (!_dispatcher.HasWorkForMovie(_file.FullName)) { try { MovieItem _movieItem = FileManager.GetMovieByFilePath(_file.FullName); FileManager.SetMovieItemStatus(_movieItem, MovieItemStatus.MetadataMissing); } catch { } } } // at this point we know what we need to do (_dispatcher has all items that needs to be generated) // decide how many threads can start generating results (sheets or thumbs) int _maxThreads = GetMaxUsableThreads(); Loggy.Logger.Debug(string.Format("UpdateManager will use {0} thread(s)", _maxThreads)); ManualResetEvent[] _doneEvents = new ManualResetEvent[_dispatcher.Count]; FileManager.ShowAdorner("Processing... Please wait...", true); try { using (Pool _pool = new Pool(_maxThreads, ThreadPriority.BelowNormal, true)) { int _i = 0; foreach (MetadataUpdateItem _item in _dispatcher) { // if cancellation was approved, jump out if (CancelProcessing.WaitOne(20)) { return; } _doneEvents[_i] = new ManualResetEvent(false); _item.DoneEvent = _doneEvents[_i]; _pool.QueueTask(new Action(_item.ThreadPoolCallback)); _i++; Helpers.DoEvents(); Thread.Sleep(20); } // go _pool.IsPaused = false; // Wait for all threads in pool to finish bool _b = false; while (!_b) { if (CancelProcessing.WaitOne(20)) { break; } if (FileManager.CancellationPending) { FileManager.CancellationPending = false; if (MessageBox.Show("Are you sure you want to stop the process?", "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes) { _pool.ClearTasks(); CancelProcessing.Set(); // signal to the other threads that job was cancelled return; } else { FileManager.ShowAdorner("Processing... Please wait...", true); } } _b = true; foreach (WaitHandle _handle in _doneEvents) { bool _cb = _handle.WaitOne(50); if (!_cb) { _b = false; } } Helpers.DoEvents(); Thread.Sleep(50); } } } finally { FileManager.HideAdorners(); } } finally { FileManager.Configuration.Options.AutogenerateMoviesheetMetadata = _autogenerateMetadata; _dispatcher.Clear(); } }