[Refactor] Update Task.Run usage to await and discard returned tasks.

Fixes some race conditions.
This commit is contained in:
2025-07-07 22:17:27 +01:00
parent 5096884f2a
commit ca1708a337
14 changed files with 257 additions and 243 deletions

View File

@@ -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

View File

@@ -59,7 +59,7 @@ public class Vfs : IDisposable
MountPoint = mountPoint
};
Task.Run(() =>
_ = Task.Run(() =>
{
_fuse.Start();

View File

@@ -498,7 +498,7 @@ public class FileExporter
if(_filesByMachine.Count == 0)
{
_machinePosition++;
Task.Run(CompressNextMachine);
_ = Task.Run(CompressNextMachine);
return;
}

View File

@@ -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))
{

View File

@@ -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));
}
}

View File

@@ -260,6 +260,6 @@ public sealed class ExportRomsViewModel : ViewModelBase
ProgressVisible = true;
Task.Run(worker.Export);
_ = Task.Run(worker.Export);
}
}

View File

@@ -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(() =>

View File

@@ -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<RomSetEventArgs> RomSetAdded;

View File

@@ -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) =>

View File

@@ -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()

View File

@@ -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);
});
}
}

View File

@@ -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)

View File

@@ -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
{

View File

@@ -128,139 +128,142 @@ public sealed class UpdateStatsViewModel : ViewModelBase
public string CloseLabel => Localization.CloseLabel;
public ReactiveCommand<Unit, Unit> 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();
}