mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 04:37:30 +02:00
CmdPal: Coalesce top-level commands list changes into a single task (#40943)
## Summary of the Pull Request Self-refresh of `MainListPage` introduced in #40132 causes unnecessary spawning of tasks by `ReapplySearchInBackground` and pushing the code down the scenic route instead of taking shortcut. This drop-in fix introduces a single-worker coalescing refresh loop to eliminate thread-pool churn and syncs state in early-return paths. ## PR Checklist - [x] Closes: #40916 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** no change - [ ] **Localization:** nothing - [ ] **Dev docs:** nothing - [ ] **New binaries:** none - [ ] **Documentation updated:** nothing <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
This commit is contained in:
@@ -6,6 +6,7 @@ using System.Collections.Immutable;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
|
using Microsoft.CmdPal.Common.Helpers;
|
||||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||||
using Microsoft.CmdPal.Ext.Apps;
|
using Microsoft.CmdPal.Ext.Apps;
|
||||||
using Microsoft.CommandPalette.Extensions;
|
using Microsoft.CommandPalette.Extensions;
|
||||||
@@ -29,6 +30,9 @@ public partial class MainListPage : DynamicListPage,
|
|||||||
private bool _includeApps;
|
private bool _includeApps;
|
||||||
private bool _filteredItemsIncludesApps;
|
private bool _filteredItemsIncludesApps;
|
||||||
|
|
||||||
|
private InterlockedBoolean _refreshRunning;
|
||||||
|
private InterlockedBoolean _refreshRequested;
|
||||||
|
|
||||||
public MainListPage(IServiceProvider serviceProvider)
|
public MainListPage(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
|
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
|
||||||
@@ -83,18 +87,47 @@ public partial class MainListPage : DynamicListPage,
|
|||||||
|
|
||||||
private void ReapplySearchInBackground()
|
private void ReapplySearchInBackground()
|
||||||
{
|
{
|
||||||
_ = Task.Run(() =>
|
_refreshRequested.Set();
|
||||||
|
if (!_refreshRunning.Set())
|
||||||
{
|
{
|
||||||
try
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = Task.Run(RunRefreshLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunRefreshLoop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
do
|
||||||
{
|
{
|
||||||
|
_refreshRequested.Clear();
|
||||||
|
lock (_tlcManager.TopLevelCommands)
|
||||||
|
{
|
||||||
|
if (_filteredItemsIncludesApps == _includeApps)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var currentSearchText = SearchText;
|
var currentSearchText = SearchText;
|
||||||
UpdateSearchText(currentSearchText, currentSearchText);
|
UpdateSearchText(currentSearchText, currentSearchText);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
while (_refreshRequested.Value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError("Failed to reload search", e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_refreshRunning.Clear();
|
||||||
|
if (_refreshRequested.Value && _refreshRunning.Set())
|
||||||
{
|
{
|
||||||
Logger.LogError("Failed to reload search", e);
|
_ = Task.Run(RunRefreshLoop);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IListItem[] GetItems()
|
public override IListItem[] GetItems()
|
||||||
@@ -126,6 +159,15 @@ public partial class MainListPage : DynamicListPage,
|
|||||||
var aliases = _serviceProvider.GetService<AliasManager>()!;
|
var aliases = _serviceProvider.GetService<AliasManager>()!;
|
||||||
if (aliases.CheckAlias(newSearch))
|
if (aliases.CheckAlias(newSearch))
|
||||||
{
|
{
|
||||||
|
if (_filteredItemsIncludesApps != _includeApps)
|
||||||
|
{
|
||||||
|
lock (_tlcManager.TopLevelCommands)
|
||||||
|
{
|
||||||
|
_filteredItemsIncludesApps = _includeApps;
|
||||||
|
_filteredItems = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,6 +180,7 @@ public partial class MainListPage : DynamicListPage,
|
|||||||
// Cleared out the filter text? easy. Reset _filteredItems, and bail out.
|
// Cleared out the filter text? easy. Reset _filteredItems, and bail out.
|
||||||
if (string.IsNullOrEmpty(newSearch))
|
if (string.IsNullOrEmpty(newSearch))
|
||||||
{
|
{
|
||||||
|
_filteredItemsIncludesApps = _includeApps;
|
||||||
_filteredItems = null;
|
_filteredItems = null;
|
||||||
RaiseItemsChanged(commands.Count);
|
RaiseItemsChanged(commands.Count);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user