Browse Source

Refactor RefreshInternal: HandleExceptions, FindAssembly, race-safe selection.

Three small follow-ups to #3705's lazy-resource fix:

* Replace `_ = RefreshInternalAsync()` with
  `RefreshInternalAsync().HandleExceptions()`. The previous fire-and-
  forget discard silently swallowed any exception thrown outside the
  explicit Catch helper on GetMetadataFileAsync; HandleExceptions is
  the codebase's idiomatic helper that surfaces the failure into the
  decompile text view.

* Look up the path-root assembly via AssemblyList.FindAssembly (an
  O(1) hash lookup keyed by OrdinalIgnoreCase, with Path.GetFullPath
  canonicalisation) instead of an O(n) foreach with case-sensitive
  string equality. Same shape used by the rest of the codebase.

* Detect the user navigating during the GetMetadataFileAsync await
  (which can take ~2s for a sizeable WPF assembly) and bail out of
  the path-restore. Without this, clicking another tree node mid-
  refresh would be silently overwritten when the deferred SelectNode
  jumped back to the captured pre-refresh path.

No behavior change for the .baml refresh fix itself.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pull/3726/head
Siegfried Pammer 2 months ago
parent
commit
4c347ef6b9
  1. 22
      ILSpy/AssemblyTree/AssemblyTreeModel.cs

22
ILSpy/AssemblyTree/AssemblyTreeModel.cs

@ -947,7 +947,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -947,7 +947,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
private void RefreshInternal()
{
_ = RefreshInternalAsync();
RefreshInternalAsync().HandleExceptions();
}
private async Task RefreshInternalAsync()
@ -958,15 +958,25 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -958,15 +958,25 @@ namespace ICSharpCode.ILSpy.AssemblyTree
ShowAssemblyList(settingsService.AssemblyListManager.LoadList(AssemblyList.ListName));
// Ensure assembly loaded before FindNodeByPath to allow lazy-loaded resource nodes to be found
// Ensure the assembly is loaded before FindNodeByPath, so lazy-loaded
// resource nodes (e.g. .baml entries) are present in the tree.
if (path?.Length > 0)
{
foreach (var asm in AssemblyList.GetAssemblies())
var rootAssembly = AssemblyList.FindAssembly(path[0]);
if (rootAssembly != null)
{
if (asm.FileName == path[0])
// FindNodeByPath() blocks the UI if the assembly is not yet loaded,
// so use an async wait instead.
var preAwaitSelection = SelectedItem;
await rootAssembly.GetMetadataFileAsync().Catch<Exception>(_ => { });
// If the user navigated to a different node while the assembly
// was loading, respect that — don't restore the pre-refresh path.
// A change to null counts too (e.g. user cleared the selection).
if (!ReferenceEquals(SelectedItem, preAwaitSelection))
{
await asm.GetMetadataFileAsync().Catch<Exception>(_ => { });
break;
RefreshDecompiledView();
return;
}
}
}

Loading…
Cancel
Save