Adding Lock to RecentCommandsManager (#40507)

According to Issue #40447 Without the Lock in RecentCommandsManager we
get Exception:
Collection was modified; enumeration operation may not execute.

It indicated that while GetCommandHistoryWeight was enumerating History,
another method (likely AddHistoryItem) modified it at the same time.
Since List is not thread-safe, simultaneous read+write can break it.

## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] **Closes:** #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Unit Tests all pass, Manually Tested as Well
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

I've checked that in this project we use the new .NET 9 locking instead
of object locking and implemented it according to rest of the locks
## Detailed Description of the Pull Request / Additional comments

I've Manually tested it and also made sure that all the unit test pass
## Validation Steps Performed
This commit is contained in:
MaoShengelia
2025-07-10 22:10:38 +04:00
committed by GitHub
parent 74b6650a19
commit dbad946b6d

View File

@@ -12,11 +12,15 @@ public partial class RecentCommandsManager : ObservableObject
[JsonInclude] [JsonInclude]
internal List<HistoryItem> History { get; set; } = []; internal List<HistoryItem> History { get; set; } = [];
private readonly Lock _lock = new();
public RecentCommandsManager() public RecentCommandsManager()
{ {
} }
public int GetCommandHistoryWeight(string commandId) public int GetCommandHistoryWeight(string commandId)
{
lock (_lock)
{ {
var entry = History var entry = History
.Index() .Index()
@@ -48,8 +52,11 @@ public partial class RecentCommandsManager : ObservableObject
return 0; return 0;
} }
}
public void AddHistoryItem(string commandId) public void AddHistoryItem(string commandId)
{
lock (_lock)
{ {
var entry = History var entry = History
.Where(item => item.CommandId == commandId) .Where(item => item.CommandId == commandId)
@@ -71,4 +78,5 @@ public partial class RecentCommandsManager : ObservableObject
History.RemoveRange(50, History.Count - 50); History.RemoveRange(50, History.Count - 50);
} }
} }
}
} }