diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index a12912b67..c1382e51e 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -19,6 +19,7 @@ using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Storage; using Flow.Launcher.Infrastructure.Logger; +using System.Threading.Channels; namespace Flow.Launcher.ViewModel { @@ -46,7 +47,7 @@ namespace Flow.Launcher.ViewModel private readonly Internationalization _translator = InternationalizationManager.Instance; - private BufferBlock _resultsUpdateQueue; + private ChannelWriter _resultsUpdateChannelWriter; private Task _resultsViewUpdateTask; #endregion @@ -85,25 +86,31 @@ namespace Flow.Launcher.ViewModel private void RegisterViewUpdate() { - _resultsUpdateQueue = new BufferBlock(); + var resultUpdateChannel = Channel.CreateUnbounded(); + _resultsUpdateChannelWriter = resultUpdateChannel.Writer; _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continueAction, TaskContinuationOptions.OnlyOnFaulted); async Task updateAction() { var queue = new Dictionary(); - while (await _resultsUpdateQueue.OutputAvailableAsync()) + var channelReader = resultUpdateChannel.Reader; + + // it is not supposed to be false because it won't be complete + while (await channelReader.WaitToReadAsync()) { - queue.Clear(); await Task.Delay(20); - while (_resultsUpdateQueue.TryReceive(out var item)) + while (channelReader.TryRead(out var item)) { if (!item.Token.IsCancellationRequested) queue[item.ID] = item; } UpdateResultView(queue.Values); + queue.Clear(); } + + Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends"); }; void continueAction(Task t) @@ -128,7 +135,10 @@ namespace Flow.Launcher.ViewModel if (e.Query.RawQuery == QueryText) // TODO: allow cancellation { PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query); - _resultsUpdateQueue.Post(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken)); + if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken))) + { + Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); + }; } }; } @@ -529,9 +539,12 @@ namespace Flow.Launcher.ViewModel await Task.Yield(); var results = await PluginManager.QueryForPlugin(plugin, query, currentCancellationToken); - if (!currentCancellationToken.IsCancellationRequested && results != null) - _resultsUpdateQueue.Post(new ResultsForUpdate(results, plugin.Metadata, query, - currentCancellationToken)); + if (currentCancellationToken.IsCancellationRequested || results == null) return; + + if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken))) + { + Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); + }; } }, currentCancellationToken) .ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception), diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs index be48f53c1..87d526fd6 100644 --- a/Flow.Launcher/ViewModel/ResultsForUpdate.cs +++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs @@ -6,7 +6,7 @@ using System.Threading; namespace Flow.Launcher.ViewModel { - public class ResultsForUpdate + public struct ResultsForUpdate { public List Results { get; } @@ -16,13 +16,6 @@ namespace Flow.Launcher.ViewModel public Query Query { get; } public CancellationToken Token { get; } - public ResultsForUpdate(List results, string resultID, CancellationToken token) - { - Results = results; - ID = resultID; - Token = token; - } - public ResultsForUpdate(List results, PluginMetadata metadata, Query query, CancellationToken token) { Results = results; diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index feab3a751..41f16f4f2 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -183,13 +183,12 @@ namespace Flow.Launcher.ViewModel private List NewResults(List newRawResults, string resultId) { if (newRawResults.Count == 0) - return Results.ToList(); + return Results; - var results = Results as IEnumerable; var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)); - return results.Where(r => r.Result.PluginID != resultId) + return Results.Where(r => r.Result.PluginID != resultId) .Concat(newResults) .OrderByDescending(r => r.Result.Score) .ToList(); @@ -198,11 +197,9 @@ namespace Flow.Launcher.ViewModel private List NewResults(IEnumerable resultsForUpdates) { if (!resultsForUpdates.Any()) - return Results.ToList(); + return Results; - var results = Results as IEnumerable; - - return results.Where(r => r != null && !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID)) + return Results.Where(r => r != null && !resultsForUpdates.Any(u => u.ID == r.Result.PluginID)) .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings))) .OrderByDescending(rv => rv.Result.Score) .ToList();