diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 00a0e1ae562..4c65f2b9fbf 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; @@ -12,9 +13,9 @@ namespace Flow.Launcher.ViewModel { public class ResultViewModel : BaseModel { - public class LazyAsync : Lazy> + public class LazyAsync : Lazy> { - private T defaultValue; + private readonly T defaultValue; private readonly Action _updateCallback; public new T Value @@ -23,21 +24,27 @@ public class LazyAsync : Lazy> { if (!IsValueCreated) { - base.Value.ContinueWith(_ => - { - _updateCallback(); - }); + _ = Exercute(); // manually use callback strategy return defaultValue; } - - if (!base.Value.IsCompleted || base.Value.IsFaulted) + + if (!base.Value.IsCompletedSuccessfully) return defaultValue; return base.Value.Result; + + // If none of the variables captured by the local function are captured by other lambdas, + // the compiler can avoid heap allocations. + async ValueTask Exercute() + { + await base.Value.ConfigureAwait(false); + _updateCallback(); + } + } } - public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory) + public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory) { if (defaultValue != null) { @@ -55,13 +62,13 @@ public ResultViewModel(Result result, Settings settings) Result = result; Image = new LazyAsync( - SetImage, + SetImage, ImageLoader.DefaultImage, () => { OnPropertyChanged(nameof(Image)); }); - } + } Settings = settings; } @@ -82,7 +89,7 @@ public ResultViewModel(Result result, Settings settings) public LazyAsync Image { get; set; } - private async Task SetImage() + private async ValueTask SetImage() { var imagePath = Result.IcoPath; if (string.IsNullOrEmpty(imagePath) && Result.Icon != null) @@ -94,7 +101,7 @@ private async Task SetImage() catch (Exception e) { Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e); - imagePath = Constant.MissingImgIcon; + return ImageLoader.DefaultImage; } }