TEdit - Terraria Map Editor - TEdit is a stand alone, open source map editor for Terraria. It lets you edit maps just like (almost) paint! It also lets you change world settings (time, bosses downed etc), edit chests and change sign, make epic dungeons, castles, cities, and add rewards for your adventurers!
The Save method was synchronous, which could block the UI thread and prevent progress updates from being reported in real-time.
New Implementation
Method: SaveAsync
Description: Converted the Save method to an asynchronous method to allow non-blocking execution and better handling of progress updates.
2. Progress Reporting in SaveAsync
Description: Added progress?.Report(...) at various stages to report updates during the save operation, including resetting time, saving the world, and completing the save process.
3. File Handling Improvements
Change: Ensured all file operations (creating temp files, copying, deleting) are handled within a lock statement to maintain thread safety.
Fix: Prevented issues with concurrent file access.
4. Task Creation and Continuation
Previous Implementation
The SaveWorldThreaded method used Task.Factory.StartNew but did not handle asynchronous behavior correctly.
New Implementation
Method: SaveWorldThreaded
Description: Updated to correctly handle asynchronous operations by awaiting the SaveAsync method.
Code:
private void SaveWorldThreaded(string filename, uint version = 0)
{
Task.Factory.StartNew(async () =>
{
ErrorLogging.TelemetryClient?.TrackEvent(nameof(SaveWorldThreaded));
try
{
OnProgressChanged(CurrentWorld, new ProgressChangedEventArgs(0, "Validating World..."));
// await CurrentWorld.ValidateAsync();
}
catch (ArgumentOutOfRangeException err)
{
string msg = "There is a problem in your world.\r\n" + $"{err.ParamName}\r\n" + $"This world may not open in Terraria\r\n" + "Would you like to save anyways??\r\n";
if (MessageBox.Show(msg, "World Error", MessageBoxButton.YesNo, MessageBoxImage.Error) != MessageBoxResult.Yes)
return;
}
catch (Exception ex)
{
string msg = "There is a problem in your world.\r\n" + $"{ex.Message}\r\n" + "This world may not open in Terraria\r\n" + "Would you like to save anyways??\r\n";
if (MessageBox.Show(msg, "World Error", MessageBoxButton.YesNo, MessageBoxImage.Error) != MessageBoxResult.Yes)
return;
}
await World.SaveAsync(CurrentWorld, filename, versionOverride: (int)version, progress: new Progress<ProgressChangedEventArgs>(e =>
{
DispatcherHelper.CheckBeginInvokeOnUI(() => OnProgressChanged(CurrentWorld, e));
}));
}).ContinueWith(t => CommandManager.InvalidateRequerySuggested(), TaskFactoryHelper.UiTaskScheduler);
}
5. Dispatcher Helper for UI Updates
Change: Used DispatcherHelper.CheckBeginInvokeOnUI to ensure progress updates are performed on the UI thread.
Fix: Correctly marshaled progress updates to the UI thread to maintain responsiveness and proper display of progress.
Conclusion
These updates improve the responsiveness and usability of the saving functionality by making it asynchronous and ensuring progress is correctly reported. The use of IProgress<ProgressChangedEventArgs> and proper handling of asynchronous tasks ensure a smoother user experience.
Changes and Fixes
Before (Stuck on validating):
After (Proper report):
1. Asynchronous Save Method
Previous Implementation
Save
method was synchronous, which could block the UI thread and prevent progress updates from being reported in real-time.New Implementation
SaveAsync
Save
method to an asynchronous method to allow non-blocking execution and better handling of progress updates.2. Progress Reporting in
SaveAsync
progress?.Report(...)
at various stages to report updates during the save operation, including resetting time, saving the world, and completing the save process.3. File Handling Improvements
lock
statement to maintain thread safety.4. Task Creation and Continuation
Previous Implementation
SaveWorldThreaded
method usedTask.Factory.StartNew
but did not handle asynchronous behavior correctly.New Implementation
SaveWorldThreaded
SaveAsync
method.Code:
5. Dispatcher Helper for UI Updates
DispatcherHelper.CheckBeginInvokeOnUI
to ensure progress updates are performed on the UI thread.Conclusion
These updates improve the responsiveness and usability of the saving functionality by making it asynchronous and ensuring progress is correctly reported. The use of
IProgress<ProgressChangedEventArgs>
and proper handling of asynchronous tasks ensure a smoother user experience.