From 70e42087966e08edc7269b5a40b53ef993ee5d59 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 1 Nov 2026 19:14:47 +0000 Subject: [PATCH] enhance: use `Dispatcher.UIThread.Post` to hand refresh results to the UI thread The background refresh tasks (branches, worktrees, tags, commits, submodules, local changes, stashes) and notification dispatching used the synchronous `Dispatcher.UIThread.Invoke`, which blocks a thread-pool thread until the UI thread has processed the update. Nothing after these calls depends on the UI update having completed (cancellation is still checked inside the lambdas), so post the updates instead. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01KCxH1zwDXLd9kfAAkcf6PZ --- src/ViewModels/Launcher.cs | 2 +- src/ViewModels/Repository.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index aad821cda..eb0ba95b5 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -441,7 +441,7 @@ private void DispatchNotification(Models.Notification notification) { if (!Dispatcher.UIThread.CheckAccess()) { - Dispatcher.UIThread.Invoke(() => DispatchNotification(notification)); + Dispatcher.UIThread.Post(() => DispatchNotification(notification)); return; } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 4d3b5541c..429f397d5 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1182,7 +1182,7 @@ public void RefreshBranches() var remotes = await new Commands.QueryRemotes(FullPath).GetResultAsync().ConfigureAwait(false); var builder = BuildBranchTree(branches, remotes); - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { if (token.IsCancellationRequested) return; @@ -1218,7 +1218,7 @@ public void RefreshWorktrees() { var worktrees = await new Commands.Worktree(FullPath).ReadAllAsync().ConfigureAwait(false); var cleaned = Worktree.Build(FullPath, worktrees); - Dispatcher.UIThread.Invoke(() => Worktrees = cleaned); + Dispatcher.UIThread.Post(() => Worktrees = cleaned); }); } @@ -1233,7 +1233,7 @@ public void RefreshTags() Task.Run(async () => { var tags = await new Commands.QueryTags(FullPath).GetResultAsync().ConfigureAwait(false); - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { if (token.IsCancellationRequested) return; @@ -1292,7 +1292,7 @@ public void RefreshCommits() } } - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { if (token.IsCancellationRequested) return; @@ -1318,7 +1318,7 @@ public void RefreshSubmodules() { if (_submodules.Count > 0) { - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { Submodules = []; VisibleSubmodules = BuildVisibleSubmodules(); @@ -1332,7 +1332,7 @@ public void RefreshSubmodules() { var submodules = await new Commands.QuerySubmodules(FullPath).GetResultAsync().ConfigureAwait(false); - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { bool hasChanged = _submodules.Count != submodules.Count; if (!hasChanged) @@ -1389,7 +1389,7 @@ public void RefreshWorkingCopyChanges() changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { if (token.IsCancellationRequested) return; @@ -1416,7 +1416,7 @@ public void RefreshStashes() Task.Run(async () => { var stashes = await new Commands.QueryStashes(FullPath).GetResultAsync().ConfigureAwait(false); - Dispatcher.UIThread.Invoke(() => + Dispatcher.UIThread.Post(() => { if (token.IsCancellationRequested) return;