[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_loop_can_be_partly_converted_to_query_highlighting = warning
resharper_member_can_be_file_local_highlighting = warning resharper_member_can_be_file_local_highlighting = warning
resharper_member_can_be_internal_highlighting = warning resharper_member_can_be_internal_highlighting = warning
resharper_member_can_be_made_static_global_highlighting = warning resharper_member_can_be_made_static_global_highlighting = none
resharper_member_can_be_made_static_local_highlighting = warning resharper_member_can_be_made_static_local_highlighting = none
resharper_member_can_be_private_global_highlighting = warning resharper_member_can_be_private_global_highlighting = warning
resharper_member_can_be_private_local_highlighting = warning resharper_member_can_be_private_local_highlighting = warning
resharper_member_can_be_protected_global_highlighting = warning resharper_member_can_be_protected_global_highlighting = warning

View File

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

View File

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

View File

@@ -58,8 +58,7 @@ public sealed class AboutViewModel : ViewModelBase
Assemblies = []; Assemblies = [];
// TODO: They do not load in time _ = Task.Run(() =>
Task.Run(() =>
{ {
foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies().OrderBy(a => a.FullName)) 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(); 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; 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(); internal void OnOpened() => RefreshFiles();
void RefreshFiles() => Task.Run(() => void RefreshFiles()
{ {
Dispatcher.UIThread.Post(() => _ = Task.Run(() =>
{ {
IsReady = false; Dispatcher.UIThread.Post(() =>
ProgressVisible = true; {
Progress2Visible = false; IsReady = false;
ProgressIsIndeterminate = true; ProgressVisible = true;
StatusMessage = Localization.SearchingForFiles; 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(); void ExecuteCloseCommand() => _view.Close();
@@ -307,7 +310,7 @@ public sealed class ImportDatFolderViewModel : ViewModelBase
_worker.SetProgressBounds += OnWorkerOnSetProgressBounds; _worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
_worker.WorkFinished += OnWorkerOnWorkFinished; _worker.WorkFinished += OnWorkerOnWorkFinished;
_worker.RomSetAdded += RomSetAdded; _worker.RomSetAdded += RomSetAdded;
Task.Run(_worker.Import); _ = Task.Run(_worker.Import);
} }
void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() => void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>

View File

@@ -161,7 +161,7 @@ public sealed class ImportDatViewModel : ViewModelBase
{ {
ProgressVisible = true; ProgressVisible = true;
_worker.RomSetAdded += RomSetAdded; _worker.RomSetAdded += RomSetAdded;
Task.Run(_worker.Import); _ = Task.Run(_worker.Import);
} }
public event EventHandler<RomSetEventArgs> RomSetAdded; public event EventHandler<RomSetEventArgs> RomSetAdded;

View File

@@ -244,7 +244,7 @@ public sealed class ImportRomFolderViewModel : ViewModelBase
worker.Finished += OnWorkerOnFinished; worker.Finished += OnWorkerOnFinished;
worker.ImportedRom += OnWorkerOnImportedRom; worker.ImportedRom += OnWorkerOnImportedRom;
Task.Run(() => worker.ProcessPath(FolderPath, true, RecurseArchivesChecked)); _ = Task.Run(() => worker.ProcessPath(FolderPath, true, RecurseArchivesChecked));
} }
void OnWorkerOnImportedRom(object sender, ImportedRomItemEventArgs args) => void OnWorkerOnImportedRom(object sender, ImportedRomItemEventArgs args) =>

View File

@@ -149,7 +149,7 @@ public class MainWindowViewModel : ViewModelBase
{ {
var dialog = new About(); var dialog = new About();
dialog.DataContext = new AboutViewModel(dialog); dialog.DataContext = new AboutViewModel(dialog);
dialog.ShowDialog(_view); _ = dialog.ShowDialog(_view);
} }
async void ExecuteImportDatCommand() async void ExecuteImportDatCommand()

View File

@@ -55,52 +55,55 @@ public sealed class RemoveDatViewModel : ViewModelBase
set => this.RaiseAndSetIfChanged(ref _statusMessage, value); set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
} }
internal void OnOpened() => Task.Run(() => internal void OnOpened()
{ {
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath); _ = Task.Run(() =>
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++)
{ {
if(sha384[i * 2] >= 0x30 && sha384[i * 2] <= 0x39) using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
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) Dispatcher.UIThread.Post(() => StatusMessage = Localization.RetrievingRomSetFromDatabase);
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); RomSet romSet = ctx.RomSets.Find(_romSetId);
string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles");
string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz");
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.FinishedWithText += CheckUnArFinished;
worker.FailedWithText += CheckUnArFailed; worker.FailedWithText += CheckUnArFailed;
Task.Run(() => worker.CheckUnAr(UnArPath)); _ = Task.Run(() => worker.CheckUnAr(UnArPath));
} }
async void CheckUnArFailed(object sender, ErrorEventArgs args) 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); 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); Dispatcher.UIThread.Post(CheckUnAr);
} }
catch(Exception e) catch(Exception e)
{ {
// TODO: Log error // TODO: Log error
Dispatcher.UIThread.Post(FailedLoadingSettings); Dispatcher.UIThread.Post(FailedLoadingSettings);
} }
}); });
}
void FailedLoadingSettings() void FailedLoadingSettings()
{ {
@@ -215,24 +218,27 @@ public sealed class SplashWindowViewModel : ViewModelBase
ExitVisible = true; ExitVisible = true;
} }
void CheckUnAr() => Task.Run(() => void CheckUnAr()
{ {
LoadingSettingsUnknown = false; _ = Task.Run(() =>
LoadingSettingsOk = true;
try
{ {
var worker = new Compression(); LoadingSettingsUnknown = false;
Settings.Settings.UnArUsable = worker.CheckUnAr(Settings.Settings.Current.UnArchiverPath); LoadingSettingsOk = true;
Dispatcher.UIThread.Post(LoadDatabase); try
} {
catch(Exception e) var worker = new Compression();
{ Settings.Settings.UnArUsable = worker.CheckUnAr(Settings.Settings.Current.UnArchiverPath);
// TODO: Log error
Dispatcher.UIThread.Post(FailedCheckUnAr); Dispatcher.UIThread.Post(LoadDatabase);
} }
}); catch(Exception e)
{
// TODO: Log error
Dispatcher.UIThread.Post(FailedCheckUnAr);
}
});
}
void FailedCheckUnAr() void FailedCheckUnAr()
{ {
@@ -246,7 +252,7 @@ public sealed class SplashWindowViewModel : ViewModelBase
CheckingUnArUnknown = false; CheckingUnArUnknown = false;
CheckingUnArOk = true; CheckingUnArOk = true;
Task.Run(() => _ = Task.Run(() =>
{ {
try try
{ {
@@ -278,7 +284,7 @@ public sealed class SplashWindowViewModel : ViewModelBase
LoadingDatabaseUnknown = false; LoadingDatabaseUnknown = false;
LoadingDatabaseOk = true; LoadingDatabaseOk = true;
Task.Run(() => _ = Task.Run(() =>
{ {
try try
{ {
@@ -308,7 +314,7 @@ public sealed class SplashWindowViewModel : ViewModelBase
MigratingDatabaseUnknown = false; MigratingDatabaseUnknown = false;
MigratingDatabaseOk = true; MigratingDatabaseOk = true;
Task.Run(() => _ = Task.Run(() =>
{ {
try try
{ {

View File

@@ -128,139 +128,142 @@ public sealed class UpdateStatsViewModel : ViewModelBase
public string CloseLabel => Localization.CloseLabel; public string CloseLabel => Localization.CloseLabel;
public ReactiveCommand<Unit, Unit> CloseCommand { get; } public ReactiveCommand<Unit, Unit> CloseCommand { get; }
internal void OnOpened() => Task.Run(() => internal void OnOpened()
{ {
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath); _ = Task.Run(() =>
Dispatcher.UIThread.Post(() =>
{ {
StatusMessage = Localization.RetrievingRomSetsFromDatabase; using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
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;
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
{ {
StatusMessage = string.Format(Localization.CalculatingStatisticsForRomSet, StatusMessage = Localization.RetrievingRomSetsFromDatabase;
romSet.Name, ProgressVisible = true;
romSet.Version, IndeterminateProgress = true;
romSet.Description);
CurrentValue = currentPos;
}); });
try long romSetCount = ctx.RomSets.LongCount();
{
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(() => { 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(() => Dispatcher.UIThread.Post(() =>
{ {
RomSets.Add(new RomSetModel StatusMessage = string.Format(Localization.CalculatingStatisticsForRomSet,
{ romSet.Name,
Id = romSet.Id, romSet.Version,
Author = romSet.Author, romSet.Description);
Comment = romSet.Comment,
Date = romSet.Date, CurrentValue = currentPos;
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
});
}); });
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(() => Dispatcher.UIThread.Post(() =>
{ {
StatusMessage = Localization.SavingChangesToDatabase; StatusMessage = Localization.Finished;
ProgressVisible = true; ProgressVisible = false;
IndeterminateProgress = true; CanClose = true;
});
}); });
}
ctx.SaveChanges();
Dispatcher.UIThread.Post(() =>
{
StatusMessage = Localization.Finished;
ProgressVisible = false;
CanClose = true;
});
});
void ExecuteCloseCommand() => _view.Close(); void ExecuteCloseCommand() => _view.Close();
} }