From 49f89e33b5127a434bd903265cf7cc977624d8ae Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 20:46:29 +0800 Subject: [PATCH] Make locking operations cancelable with tokens Updated `_semaphore.WaitAsync` in `EverythingAPI.cs` to accept a `CancellationToken` and handle `OperationCanceledException` gracefully, returning `false` instead of propagating the exception. Refactored locking mechanisms in `Main.cs` to use `CancellationToken` for `_win32sLock` and `_uwpsLock`. Added `try-catch` blocks to handle `OperationCanceledException` and ensure proper lock release. Methods now return `emptyResults` when operations are canceled. --- .../Search/Everything/EverythingAPI.cs | 12 +++++++---- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 20 ++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index d06fdfa98..eccbb2bf9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -48,13 +48,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { - // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller. - await _semaphore.WaitAsync(); + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + return false; + } try { - if (token.IsCancellationRequested) return false; _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; return result; diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index aac5de2c2..a0f418fe0 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -84,35 +84,31 @@ namespace Flow.Launcher.Plugin.Program { var resultList = await Task.Run(async () => { - // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller. Context.API.LogDebug(ClassName, "Preparing win32 programs"); List win32s; - await _win32sLock.WaitAsync(); try { + await _win32sLock.WaitAsync(token); win32s = [.. _win32s]; - if (token.IsCancellationRequested) return emptyResults; } - finally + catch (OperationCanceledException) { - _win32sLock.Release(); + return emptyResults; } + _win32sLock.Release(); - // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller. Context.API.LogDebug(ClassName, "Preparing UWP programs"); List uwps; - await _uwpsLock.WaitAsync(); try { + await _uwpsLock.WaitAsync(token); uwps = [.. _uwps]; - if (token.IsCancellationRequested) return emptyResults; } - finally + catch (OperationCanceledException) { - _uwpsLock.Release(); + return emptyResults; } + _uwpsLock.Release(); Context.API.LogDebug(ClassName, "Start querying programs"); try