From ca1708a337fb8aac95c6af5c1fd80bd48dd72e88 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 7 Jul 2025 22:17:27 +0100 Subject: [PATCH] [Refactor] Update Task.Run usage to await and discard returned tasks. Fixes some race conditions. --- .editorconfig | 4 +- RomRepoMgr.Core/Filesystem/Vfs.cs | 2 +- RomRepoMgr.Core/Workers/FileExporter.cs | 2 +- RomRepoMgr/ViewModels/AboutViewModel.cs | 3 +- RomRepoMgr/ViewModels/ExportDatViewModel.cs | 2 +- RomRepoMgr/ViewModels/ExportRomsViewModel.cs | 2 +- .../ViewModels/ImportDatFolderViewModel.cs | 91 +++---- RomRepoMgr/ViewModels/ImportDatViewModel.cs | 2 +- .../ViewModels/ImportRomFolderViewModel.cs | 2 +- RomRepoMgr/ViewModels/MainWindowViewModel.cs | 2 +- RomRepoMgr/ViewModels/RemoveDatViewModel.cs | 87 +++---- RomRepoMgr/ViewModels/SettingsViewModel.cs | 2 +- .../ViewModels/SplashWindowViewModel.cs | 64 ++--- RomRepoMgr/ViewModels/UpdateStatsViewModel.cs | 235 +++++++++--------- 14 files changed, 257 insertions(+), 243 deletions(-) diff --git a/.editorconfig b/.editorconfig index b656bd8..75c539e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -390,8 +390,8 @@ resharper_loop_can_be_converted_to_query_highlighting resharper_loop_can_be_partly_converted_to_query_highlighting = warning resharper_member_can_be_file_local_highlighting = warning resharper_member_can_be_internal_highlighting = warning -resharper_member_can_be_made_static_global_highlighting = warning -resharper_member_can_be_made_static_local_highlighting = warning +resharper_member_can_be_made_static_global_highlighting = none +resharper_member_can_be_made_static_local_highlighting = none resharper_member_can_be_private_global_highlighting = warning resharper_member_can_be_private_local_highlighting = warning resharper_member_can_be_protected_global_highlighting = warning diff --git a/RomRepoMgr.Core/Filesystem/Vfs.cs b/RomRepoMgr.Core/Filesystem/Vfs.cs index 9d9401f..9fa5d26 100644 --- a/RomRepoMgr.Core/Filesystem/Vfs.cs +++ b/RomRepoMgr.Core/Filesystem/Vfs.cs @@ -59,7 +59,7 @@ public class Vfs : IDisposable MountPoint = mountPoint }; - Task.Run(() => + _ = Task.Run(() => { _fuse.Start(); diff --git a/RomRepoMgr.Core/Workers/FileExporter.cs b/RomRepoMgr.Core/Workers/FileExporter.cs index be3f33c..d19b831 100644 --- a/RomRepoMgr.Core/Workers/FileExporter.cs +++ b/RomRepoMgr.Core/Workers/FileExporter.cs @@ -498,7 +498,7 @@ public class FileExporter if(_filesByMachine.Count == 0) { _machinePosition++; - Task.Run(CompressNextMachine); + _ = Task.Run(CompressNextMachine); return; } diff --git a/RomRepoMgr/ViewModels/AboutViewModel.cs b/RomRepoMgr/ViewModels/AboutViewModel.cs index 89acbbe..03400d9 100644 --- a/RomRepoMgr/ViewModels/AboutViewModel.cs +++ b/RomRepoMgr/ViewModels/AboutViewModel.cs @@ -58,8 +58,7 @@ public sealed class AboutViewModel : ViewModelBase Assemblies = []; - // TODO: They do not load in time - Task.Run(() => + _ = Task.Run(() => { foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies().OrderBy(a => a.FullName)) { diff --git a/RomRepoMgr/ViewModels/ExportDatViewModel.cs b/RomRepoMgr/ViewModels/ExportDatViewModel.cs index d138888..55a6641 100644 --- a/RomRepoMgr/ViewModels/ExportDatViewModel.cs +++ b/RomRepoMgr/ViewModels/ExportDatViewModel.cs @@ -145,6 +145,6 @@ public sealed class ExportDatViewModel : ViewModelBase if(!File.Exists(compressedDatPath)) _view.Close(); - Task.Run(() => _worker.DecompressFile(compressedDatPath, _outPath)); + _ = Task.Run(() => _worker.DecompressFile(compressedDatPath, _outPath)); } } \ No newline at end of file diff --git a/RomRepoMgr/ViewModels/ExportRomsViewModel.cs b/RomRepoMgr/ViewModels/ExportRomsViewModel.cs index 46ae497..75ec125 100644 --- a/RomRepoMgr/ViewModels/ExportRomsViewModel.cs +++ b/RomRepoMgr/ViewModels/ExportRomsViewModel.cs @@ -260,6 +260,6 @@ public sealed class ExportRomsViewModel : ViewModelBase ProgressVisible = true; - Task.Run(worker.Export); + _ = Task.Run(worker.Export); } } \ No newline at end of file diff --git a/RomRepoMgr/ViewModels/ImportDatFolderViewModel.cs b/RomRepoMgr/ViewModels/ImportDatFolderViewModel.cs index 1c34f64..e8add54 100644 --- a/RomRepoMgr/ViewModels/ImportDatFolderViewModel.cs +++ b/RomRepoMgr/ViewModels/ImportDatFolderViewModel.cs @@ -216,52 +216,55 @@ public sealed class ImportDatFolderViewModel : ViewModelBase internal void OnOpened() => RefreshFiles(); - void RefreshFiles() => Task.Run(() => + void RefreshFiles() { - Dispatcher.UIThread.Post(() => + _ = Task.Run(() => { - IsReady = false; - ProgressVisible = true; - Progress2Visible = false; - ProgressIsIndeterminate = true; - StatusMessage = Localization.SearchingForFiles; + Dispatcher.UIThread.Post(() => + { + IsReady = false; + ProgressVisible = true; + Progress2Visible = false; + ProgressIsIndeterminate = true; + StatusMessage = Localization.SearchingForFiles; + }); + + if(_allFilesChecked) + { + _datFiles = Directory + .GetFiles(FolderPath, + "*.*", + _recursiveChecked ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) + .OrderBy(f => f) + .ToArray(); + } + else + { + string[] dats = Directory.GetFiles(FolderPath, + "*.dat", + _recursiveChecked + ? SearchOption.AllDirectories + : SearchOption.TopDirectoryOnly); + + string[] xmls = Directory.GetFiles(FolderPath, + "*.xml", + _recursiveChecked + ? SearchOption.AllDirectories + : SearchOption.TopDirectoryOnly); + + _datFiles = dats.Concat(xmls).OrderBy(f => f).ToArray(); + } + + Dispatcher.UIThread.Post(() => + { + IsReady = true; + ProgressVisible = false; + StatusMessage = string.Format(Localization.FoundFiles, _datFiles.Length); + CanClose = true; + CanStart = true; + }); }); - - if(_allFilesChecked) - { - _datFiles = Directory - .GetFiles(FolderPath, - "*.*", - _recursiveChecked ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) - .OrderBy(f => f) - .ToArray(); - } - else - { - string[] dats = Directory.GetFiles(FolderPath, - "*.dat", - _recursiveChecked - ? SearchOption.AllDirectories - : SearchOption.TopDirectoryOnly); - - string[] xmls = Directory.GetFiles(FolderPath, - "*.xml", - _recursiveChecked - ? SearchOption.AllDirectories - : SearchOption.TopDirectoryOnly); - - _datFiles = dats.Concat(xmls).OrderBy(f => f).ToArray(); - } - - Dispatcher.UIThread.Post(() => - { - IsReady = true; - ProgressVisible = false; - StatusMessage = string.Format(Localization.FoundFiles, _datFiles.Length); - CanClose = true; - CanStart = true; - }); - }); + } void ExecuteCloseCommand() => _view.Close(); @@ -307,7 +310,7 @@ public sealed class ImportDatFolderViewModel : ViewModelBase _worker.SetProgressBounds += OnWorkerOnSetProgressBounds; _worker.WorkFinished += OnWorkerOnWorkFinished; _worker.RomSetAdded += RomSetAdded; - Task.Run(_worker.Import); + _ = Task.Run(_worker.Import); } void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() => diff --git a/RomRepoMgr/ViewModels/ImportDatViewModel.cs b/RomRepoMgr/ViewModels/ImportDatViewModel.cs index 2e23769..0b5f225 100644 --- a/RomRepoMgr/ViewModels/ImportDatViewModel.cs +++ b/RomRepoMgr/ViewModels/ImportDatViewModel.cs @@ -161,7 +161,7 @@ public sealed class ImportDatViewModel : ViewModelBase { ProgressVisible = true; _worker.RomSetAdded += RomSetAdded; - Task.Run(_worker.Import); + _ = Task.Run(_worker.Import); } public event EventHandler RomSetAdded; diff --git a/RomRepoMgr/ViewModels/ImportRomFolderViewModel.cs b/RomRepoMgr/ViewModels/ImportRomFolderViewModel.cs index 5404c18..4114953 100644 --- a/RomRepoMgr/ViewModels/ImportRomFolderViewModel.cs +++ b/RomRepoMgr/ViewModels/ImportRomFolderViewModel.cs @@ -244,7 +244,7 @@ public sealed class ImportRomFolderViewModel : ViewModelBase worker.Finished += OnWorkerOnFinished; worker.ImportedRom += OnWorkerOnImportedRom; - Task.Run(() => worker.ProcessPath(FolderPath, true, RecurseArchivesChecked)); + _ = Task.Run(() => worker.ProcessPath(FolderPath, true, RecurseArchivesChecked)); } void OnWorkerOnImportedRom(object sender, ImportedRomItemEventArgs args) => diff --git a/RomRepoMgr/ViewModels/MainWindowViewModel.cs b/RomRepoMgr/ViewModels/MainWindowViewModel.cs index 45217a4..0e02404 100644 --- a/RomRepoMgr/ViewModels/MainWindowViewModel.cs +++ b/RomRepoMgr/ViewModels/MainWindowViewModel.cs @@ -149,7 +149,7 @@ public class MainWindowViewModel : ViewModelBase { var dialog = new About(); dialog.DataContext = new AboutViewModel(dialog); - dialog.ShowDialog(_view); + _ = dialog.ShowDialog(_view); } async void ExecuteImportDatCommand() diff --git a/RomRepoMgr/ViewModels/RemoveDatViewModel.cs b/RomRepoMgr/ViewModels/RemoveDatViewModel.cs index 9a68eb0..ef5682d 100644 --- a/RomRepoMgr/ViewModels/RemoveDatViewModel.cs +++ b/RomRepoMgr/ViewModels/RemoveDatViewModel.cs @@ -55,52 +55,55 @@ public sealed class RemoveDatViewModel : ViewModelBase set => this.RaiseAndSetIfChanged(ref _statusMessage, value); } - internal void OnOpened() => Task.Run(() => + internal void OnOpened() { - using var ctx = Context.Create(Settings.Settings.Current.DatabasePath); - - Dispatcher.UIThread.Post(() => StatusMessage = Localization.RetrievingRomSetFromDatabase); - - RomSet romSet = ctx.RomSets.Find(_romSetId); - - if(romSet == null) return; - - Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingRomSetFromDatabase); - - ctx.RomSets.Remove(romSet); - - Dispatcher.UIThread.Post(() => StatusMessage = Localization.SavingChangesToDatabase); - - ctx.SaveChanges(); - - Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingDatFileFromRepo); - - var sha384Bytes = new byte[48]; - string sha384 = romSet.Sha384; - - for(var i = 0; i < 48; i++) + _ = Task.Run(() => { - if(sha384[i * 2] >= 0x30 && sha384[i * 2] <= 0x39) - sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10); - else if(sha384[i * 2] >= 0x41 && sha384[i * 2] <= 0x46) - sha384Bytes[i] = (byte)((sha384[i * 2] - 0x37) * 0x10); - else if(sha384[i * 2] >= 0x61 && sha384[i * 2] <= 0x66) - sha384Bytes[i] = (byte)((sha384[i * 2] - 0x57) * 0x10); + using var ctx = Context.Create(Settings.Settings.Current.DatabasePath); - if(sha384[i * 2 + 1] >= 0x30 && sha384[i * 2 + 1] <= 0x39) - sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x30); - else if(sha384[i * 2 + 1] >= 0x41 && sha384[i * 2 + 1] <= 0x46) - sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x37); - else if(sha384[i * 2 + 1] >= 0x61 && sha384[i * 2 + 1] <= 0x66) - sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x57); - } + Dispatcher.UIThread.Post(() => StatusMessage = Localization.RetrievingRomSetFromDatabase); - string datHash32 = Base32.ToBase32String(sha384Bytes); - string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles"); - string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz"); + RomSet romSet = ctx.RomSets.Find(_romSetId); - if(File.Exists(compressedDatPath)) File.Delete(compressedDatPath); + if(romSet == null) return; - Dispatcher.UIThread.Post(_view.Close); - }); + Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingRomSetFromDatabase); + + ctx.RomSets.Remove(romSet); + + Dispatcher.UIThread.Post(() => StatusMessage = Localization.SavingChangesToDatabase); + + ctx.SaveChanges(); + + Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingDatFileFromRepo); + + var sha384Bytes = new byte[48]; + string sha384 = romSet.Sha384; + + for(var i = 0; i < 48; i++) + { + if(sha384[i * 2] >= 0x30 && sha384[i * 2] <= 0x39) + sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10); + else if(sha384[i * 2] >= 0x41 && sha384[i * 2] <= 0x46) + sha384Bytes[i] = (byte)((sha384[i * 2] - 0x37) * 0x10); + else if(sha384[i * 2] >= 0x61 && sha384[i * 2] <= 0x66) + sha384Bytes[i] = (byte)((sha384[i * 2] - 0x57) * 0x10); + + if(sha384[i * 2 + 1] >= 0x30 && sha384[i * 2 + 1] <= 0x39) + sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x30); + else if(sha384[i * 2 + 1] >= 0x41 && sha384[i * 2 + 1] <= 0x46) + sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x37); + else if(sha384[i * 2 + 1] >= 0x61 && sha384[i * 2 + 1] <= 0x66) + sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x57); + } + + string datHash32 = Base32.ToBase32String(sha384Bytes); + string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles"); + string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz"); + + if(File.Exists(compressedDatPath)) File.Delete(compressedDatPath); + + Dispatcher.UIThread.Post(_view.Close); + }); + } } \ No newline at end of file diff --git a/RomRepoMgr/ViewModels/SettingsViewModel.cs b/RomRepoMgr/ViewModels/SettingsViewModel.cs index 540f922..59e6afe 100644 --- a/RomRepoMgr/ViewModels/SettingsViewModel.cs +++ b/RomRepoMgr/ViewModels/SettingsViewModel.cs @@ -146,7 +146,7 @@ public sealed class SettingsViewModel : ViewModelBase worker.FinishedWithText += CheckUnArFinished; worker.FailedWithText += CheckUnArFailed; - Task.Run(() => worker.CheckUnAr(UnArPath)); + _ = Task.Run(() => worker.CheckUnAr(UnArPath)); } async void CheckUnArFailed(object sender, ErrorEventArgs args) diff --git a/RomRepoMgr/ViewModels/SplashWindowViewModel.cs b/RomRepoMgr/ViewModels/SplashWindowViewModel.cs index 0ceac99..2cfddb2 100644 --- a/RomRepoMgr/ViewModels/SplashWindowViewModel.cs +++ b/RomRepoMgr/ViewModels/SplashWindowViewModel.cs @@ -193,20 +193,23 @@ public sealed class SplashWindowViewModel : ViewModelBase internal void OnOpened() => Dispatcher.UIThread.Post(LoadSettings); - void LoadSettings() => Task.Run(() => + void LoadSettings() { - try + _ = Task.Run(() => { - Settings.Settings.LoadSettings(); + try + { + Settings.Settings.LoadSettings(); - Dispatcher.UIThread.Post(CheckUnAr); - } - catch(Exception e) - { - // TODO: Log error - Dispatcher.UIThread.Post(FailedLoadingSettings); - } - }); + Dispatcher.UIThread.Post(CheckUnAr); + } + catch(Exception e) + { + // TODO: Log error + Dispatcher.UIThread.Post(FailedLoadingSettings); + } + }); + } void FailedLoadingSettings() { @@ -215,24 +218,27 @@ public sealed class SplashWindowViewModel : ViewModelBase ExitVisible = true; } - void CheckUnAr() => Task.Run(() => + void CheckUnAr() { - LoadingSettingsUnknown = false; - LoadingSettingsOk = true; - - try + _ = Task.Run(() => { - var worker = new Compression(); - Settings.Settings.UnArUsable = worker.CheckUnAr(Settings.Settings.Current.UnArchiverPath); + LoadingSettingsUnknown = false; + LoadingSettingsOk = true; - Dispatcher.UIThread.Post(LoadDatabase); - } - catch(Exception e) - { - // TODO: Log error - Dispatcher.UIThread.Post(FailedCheckUnAr); - } - }); + try + { + var worker = new Compression(); + Settings.Settings.UnArUsable = worker.CheckUnAr(Settings.Settings.Current.UnArchiverPath); + + Dispatcher.UIThread.Post(LoadDatabase); + } + catch(Exception e) + { + // TODO: Log error + Dispatcher.UIThread.Post(FailedCheckUnAr); + } + }); + } void FailedCheckUnAr() { @@ -246,7 +252,7 @@ public sealed class SplashWindowViewModel : ViewModelBase CheckingUnArUnknown = false; CheckingUnArOk = true; - Task.Run(() => + _ = Task.Run(() => { try { @@ -278,7 +284,7 @@ public sealed class SplashWindowViewModel : ViewModelBase LoadingDatabaseUnknown = false; LoadingDatabaseOk = true; - Task.Run(() => + _ = Task.Run(() => { try { @@ -308,7 +314,7 @@ public sealed class SplashWindowViewModel : ViewModelBase MigratingDatabaseUnknown = false; MigratingDatabaseOk = true; - Task.Run(() => + _ = Task.Run(() => { try { diff --git a/RomRepoMgr/ViewModels/UpdateStatsViewModel.cs b/RomRepoMgr/ViewModels/UpdateStatsViewModel.cs index c1b93fd..e87b2ba 100644 --- a/RomRepoMgr/ViewModels/UpdateStatsViewModel.cs +++ b/RomRepoMgr/ViewModels/UpdateStatsViewModel.cs @@ -128,139 +128,142 @@ public sealed class UpdateStatsViewModel : ViewModelBase public string CloseLabel => Localization.CloseLabel; public ReactiveCommand CloseCommand { get; } - internal void OnOpened() => Task.Run(() => + internal void OnOpened() { - using var ctx = Context.Create(Settings.Settings.Current.DatabasePath); - - Dispatcher.UIThread.Post(() => + _ = Task.Run(() => { - StatusMessage = Localization.RetrievingRomSetsFromDatabase; - ProgressVisible = true; - IndeterminateProgress = true; - }); - - long romSetCount = ctx.RomSets.LongCount(); - - Dispatcher.UIThread.Post(() => { StatusMessage = Localization.RemovingOldStatistics; }); - - ctx.Database.ExecuteSql($"DELETE FROM \"RomSetStats\""); - - Dispatcher.UIThread.Post(() => - { - IndeterminateProgress = false; - MinimumValue = 0; - MaximumValue = romSetCount; - CurrentValue = 0; - }); - - long pos = 0; - - foreach(RomSet romSet in ctx.RomSets) - { - long currentPos = pos; + using var ctx = Context.Create(Settings.Settings.Current.DatabasePath); Dispatcher.UIThread.Post(() => { - StatusMessage = string.Format(Localization.CalculatingStatisticsForRomSet, - romSet.Name, - romSet.Version, - romSet.Description); - - CurrentValue = currentPos; + StatusMessage = Localization.RetrievingRomSetsFromDatabase; + ProgressVisible = true; + IndeterminateProgress = true; }); - try - { - RomSetStat stats = ctx.RomSets.Where(r => r.Id == romSet.Id) - .Select(r => new RomSetStat - { - RomSetId = r.Id, - TotalMachines = r.Machines.Count, - CompleteMachines = - r.Machines.Count(m => m.Files.Count > 0 && - m.Disks.Count == 0 && - m.Files.All(f => f.File.IsInRepo)) + - r.Machines.Count(m => m.Disks.Count > 0 && - m.Files.Count == 0 && - m.Disks.All(f => f.Disk.IsInRepo)) + - r.Machines.Count(m => m.Files.Count > 0 && - m.Disks.Count > 0 && - m.Files.All(f => f.File.IsInRepo) && - m.Disks.All(f => f.Disk.IsInRepo)), - IncompleteMachines = - r.Machines.Count(m => m.Files.Count > 0 && - m.Disks.Count == 0 && - m.Files.Any(f => !f.File.IsInRepo)) + - r.Machines.Count(m => m.Disks.Count > 0 && - m.Files.Count == 0 && - m.Disks.Any(f => !f.Disk.IsInRepo)) + - r.Machines.Count(m => m.Files.Count > 0 && - m.Disks.Count > 0 && - (m.Files.Any(f => !f.File.IsInRepo) || - m.Disks.Any(f => !f.Disk.IsInRepo))), - TotalRoms = - r.Machines.Sum(m => m.Files.Count) + - r.Machines.Sum(m => m.Disks.Count) + - r.Machines.Sum(m => m.Medias.Count), - HaveRoms = r.Machines.Sum(m => m.Files.Count(f => f.File.IsInRepo)) + - r.Machines.Sum(m => m.Disks.Count(f => f.Disk.IsInRepo)) + - r.Machines.Sum(m => m.Medias.Count(f => f.Media.IsInRepo)), - MissRoms = r.Machines.Sum(m => m.Files.Count(f => !f.File.IsInRepo)) + - r.Machines.Sum(m => m.Disks.Count(f => !f.Disk.IsInRepo)) + - r.Machines.Sum(m => m.Medias.Count(f => !f.Media.IsInRepo)) - }) - .FirstOrDefault(); + long romSetCount = ctx.RomSets.LongCount(); - ctx.RomSetStats.Add(stats); + Dispatcher.UIThread.Post(() => { StatusMessage = Localization.RemovingOldStatistics; }); + + ctx.Database.ExecuteSql($"DELETE FROM \"RomSetStats\""); + + Dispatcher.UIThread.Post(() => + { + IndeterminateProgress = false; + MinimumValue = 0; + MaximumValue = romSetCount; + CurrentValue = 0; + }); + + long pos = 0; + + foreach(RomSet romSet in ctx.RomSets) + { + long currentPos = pos; Dispatcher.UIThread.Post(() => { - RomSets.Add(new RomSetModel - { - Id = romSet.Id, - Author = romSet.Author, - Comment = romSet.Comment, - Date = romSet.Date, - Description = romSet.Description, - Filename = romSet.Filename, - Homepage = romSet.Homepage, - Name = romSet.Name, - Sha384 = romSet.Sha384, - Version = romSet.Version, - TotalMachines = stats.TotalMachines, - CompleteMachines = stats.CompleteMachines, - IncompleteMachines = stats.IncompleteMachines, - TotalRoms = stats.TotalRoms, - HaveRoms = stats.HaveRoms, - MissRoms = stats.MissRoms, - Category = romSet.Category - }); + StatusMessage = string.Format(Localization.CalculatingStatisticsForRomSet, + romSet.Name, + romSet.Version, + romSet.Description); + + CurrentValue = currentPos; }); + + try + { + RomSetStat stats = ctx.RomSets.Where(r => r.Id == romSet.Id) + .Select(r => new RomSetStat + { + RomSetId = r.Id, + TotalMachines = r.Machines.Count, + CompleteMachines = + r.Machines.Count(m => m.Files.Count > 0 && + m.Disks.Count == 0 && + m.Files.All(f => f.File.IsInRepo)) + + r.Machines.Count(m => m.Disks.Count > 0 && + m.Files.Count == 0 && + m.Disks.All(f => f.Disk.IsInRepo)) + + r.Machines.Count(m => m.Files.Count > 0 && + m.Disks.Count > 0 && + m.Files.All(f => f.File.IsInRepo) && + m.Disks.All(f => f.Disk.IsInRepo)), + IncompleteMachines = + r.Machines.Count(m => m.Files.Count > 0 && + m.Disks.Count == 0 && + m.Files.Any(f => !f.File.IsInRepo)) + + r.Machines.Count(m => m.Disks.Count > 0 && + m.Files.Count == 0 && + m.Disks.Any(f => !f.Disk.IsInRepo)) + + r.Machines.Count(m => m.Files.Count > 0 && + m.Disks.Count > 0 && + (m.Files.Any(f => !f.File.IsInRepo) || + m.Disks.Any(f => !f.Disk.IsInRepo))), + TotalRoms = + r.Machines.Sum(m => m.Files.Count) + + r.Machines.Sum(m => m.Disks.Count) + + r.Machines.Sum(m => m.Medias.Count), + HaveRoms = r.Machines.Sum(m => m.Files.Count(f => f.File.IsInRepo)) + + r.Machines.Sum(m => m.Disks.Count(f => f.Disk.IsInRepo)) + + r.Machines.Sum(m => m.Medias.Count(f => f.Media.IsInRepo)), + MissRoms = r.Machines.Sum(m => m.Files.Count(f => !f.File.IsInRepo)) + + r.Machines.Sum(m => m.Disks.Count(f => !f.Disk.IsInRepo)) + + r.Machines.Sum(m => m.Medias.Count(f => !f.Media.IsInRepo)) + }) + .FirstOrDefault(); + + ctx.RomSetStats.Add(stats); + + Dispatcher.UIThread.Post(() => + { + RomSets.Add(new RomSetModel + { + Id = romSet.Id, + Author = romSet.Author, + Comment = romSet.Comment, + Date = romSet.Date, + Description = romSet.Description, + Filename = romSet.Filename, + Homepage = romSet.Homepage, + Name = romSet.Name, + Sha384 = romSet.Sha384, + Version = romSet.Version, + TotalMachines = stats.TotalMachines, + CompleteMachines = stats.CompleteMachines, + IncompleteMachines = stats.IncompleteMachines, + TotalRoms = stats.TotalRoms, + HaveRoms = stats.HaveRoms, + MissRoms = stats.MissRoms, + Category = romSet.Category + }); + }); + } + catch(Exception) + { + // Ignored + } + + pos++; } - catch(Exception) + + Dispatcher.UIThread.Post(() => { - // Ignored - } + StatusMessage = Localization.SavingChangesToDatabase; + ProgressVisible = true; + IndeterminateProgress = true; + }); - pos++; - } + ctx.SaveChanges(); - Dispatcher.UIThread.Post(() => - { - StatusMessage = Localization.SavingChangesToDatabase; - ProgressVisible = true; - IndeterminateProgress = true; + Dispatcher.UIThread.Post(() => + { + StatusMessage = Localization.Finished; + ProgressVisible = false; + CanClose = true; + }); }); - - ctx.SaveChanges(); - - Dispatcher.UIThread.Post(() => - { - StatusMessage = Localization.Finished; - ProgressVisible = false; - CanClose = true; - }); - }); + } void ExecuteCloseCommand() => _view.Close(); } \ No newline at end of file