diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs index 3b4bc56ffd..59a6d04ca4 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs @@ -34,9 +34,9 @@ public sealed class IconCacheService(DispatcherQueue dispatcherQueue) { return await StreamToIconSource(icon.Data.Unsafe!); } - catch + catch (Exception ex) { - Debug.WriteLine("Failed to load icon from stream"); + Debug.WriteLine("Failed to load icon from stream: " + ex); } } } @@ -63,17 +63,37 @@ public sealed class IconCacheService(DispatcherQueue dispatcherQueue) { // Return the bitmap image via TaskCompletionSource. Using WCT's EnqueueAsync does not suffice here, since if // we're already on the thread of the DispatcherQueue then it just directly calls the function, with no async involved. - var completionSource = new TaskCompletionSource(); - dispatcherQueue.TryEnqueue(async () => + return await TryEnqueueAsync(dispatcherQueue, async () => { using var bitmapStream = await iconStreamRef.OpenReadAsync(); var itemImage = new BitmapImage(); await itemImage.SetSourceAsync(bitmapStream); - completionSource.TrySetResult(itemImage); + return itemImage; + }); + } + + private static Task TryEnqueueAsync(DispatcherQueue dispatcher, Func> function) + { + var completionSource = new TaskCompletionSource(); + + var enqueued = dispatcher.TryEnqueue(DispatcherQueuePriority.Normal, async void () => + { + try + { + var result = await function(); + completionSource.SetResult(result); + } + catch (Exception ex) + { + completionSource.SetException(ex); + } }); - var bitmapImage = await completionSource.Task; + if (!enqueued) + { + completionSource.SetException(new InvalidOperationException("Failed to enqueue the operation on the UI dispatcher")); + } - return bitmapImage; + return completionSource.Task; } }