From 8a2a71000ec369bf17d57d3c9311840e731ea41e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 15 Feb 2021 17:58:15 +0800 Subject: [PATCH 1/4] Use Channel instead of BufferBlock --- Flow.Launcher/ViewModel/MainViewModel.cs | 31 ++++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index a12912b67bf..0cf4b11dcd0 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -19,6 +19,7 @@ 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 @@ public class MainViewModel : BaseModel, ISavable private readonly Internationalization _translator = InternationalizationManager.Instance; - private BufferBlock _resultsUpdateQueue; + private Channel _resultsUpdateQueue; private Task _resultsViewUpdateTask; #endregion @@ -85,18 +86,21 @@ public MainViewModel(Settings settings) private void RegisterViewUpdate() { - _resultsUpdateQueue = new BufferBlock(); + _resultsUpdateQueue = Channel.CreateUnbounded(); _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continueAction, TaskContinuationOptions.OnlyOnFaulted); async Task updateAction() { var queue = new Dictionary(); - while (await _resultsUpdateQueue.OutputAvailableAsync()) + var queueReader = _resultsUpdateQueue.Reader; + + // it is not supposed to be false because it won't be complete + while (await queueReader.WaitToReadAsync()) { queue.Clear(); await Task.Delay(20); - while (_resultsUpdateQueue.TryReceive(out var item)) + await foreach (var item in queueReader.ReadAllAsync()) { if (!item.Token.IsCancellationRequested) queue[item.ID] = item; @@ -104,6 +108,8 @@ async Task updateAction() UpdateResultView(queue.Values); } + + Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends"); }; void continueAction(Task t) @@ -128,7 +134,10 @@ private void RegisterResultsUpdatedEvent() 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 (!_resultsUpdateQueue.Writer.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken))) + { + Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); + }; } }; } @@ -529,9 +538,15 @@ async Task QueryTask(PluginPair plugin) 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 (!_resultsUpdateQueue.Writer.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), From a7811f312c1add5f6a16e44970ebd010173abed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 15 Feb 2021 18:19:30 +0800 Subject: [PATCH 2/4] fix an issue --- Flow.Launcher/ViewModel/MainViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 0cf4b11dcd0..3e71adcd147 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -98,15 +98,15 @@ async Task updateAction() // it is not supposed to be false because it won't be complete while (await queueReader.WaitToReadAsync()) { - queue.Clear(); await Task.Delay(20); - await foreach (var item in queueReader.ReadAllAsync()) + while (queueReader.TryRead(out var item)) { if (!item.Token.IsCancellationRequested) queue[item.ID] = item; } UpdateResultView(queue.Values); + queue.Clear(); } Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends"); From b017bdeed435f810909e2afd2c9f49bb41ba3f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 15 Feb 2021 18:37:42 +0800 Subject: [PATCH 3/4] fix format --- Flow.Launcher/ViewModel/MainViewModel.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 3e71adcd147..90bdc38c8ec 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -538,10 +538,7 @@ async Task QueryTask(PluginPair plugin) await Task.Yield(); var results = await PluginManager.QueryForPlugin(plugin, query, currentCancellationToken); - if (currentCancellationToken.IsCancellationRequested || results == null) - { - return; - } + if (currentCancellationToken.IsCancellationRequested || results == null) return; if (!_resultsUpdateQueue.Writer.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken))) { From 350499a4801a9a60ba00a811b79bc7785b4da33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 16 Feb 2021 02:12:28 +0800 Subject: [PATCH 4/4] Optimize Logic and code --- Flow.Launcher/ViewModel/MainViewModel.cs | 17 +++++++++-------- Flow.Launcher/ViewModel/ResultsForUpdate.cs | 9 +-------- Flow.Launcher/ViewModel/ResultsViewModel.cs | 11 ++++------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 90bdc38c8ec..c1382e51eec 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -47,7 +47,7 @@ public class MainViewModel : BaseModel, ISavable private readonly Internationalization _translator = InternationalizationManager.Instance; - private Channel _resultsUpdateQueue; + private ChannelWriter _resultsUpdateChannelWriter; private Task _resultsViewUpdateTask; #endregion @@ -86,20 +86,21 @@ public MainViewModel(Settings settings) private void RegisterViewUpdate() { - _resultsUpdateQueue = Channel.CreateUnbounded(); + var resultUpdateChannel = Channel.CreateUnbounded(); + _resultsUpdateChannelWriter = resultUpdateChannel.Writer; _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continueAction, TaskContinuationOptions.OnlyOnFaulted); async Task updateAction() { var queue = new Dictionary(); - var queueReader = _resultsUpdateQueue.Reader; + var channelReader = resultUpdateChannel.Reader; // it is not supposed to be false because it won't be complete - while (await queueReader.WaitToReadAsync()) + while (await channelReader.WaitToReadAsync()) { await Task.Delay(20); - while (queueReader.TryRead(out var item)) + while (channelReader.TryRead(out var item)) { if (!item.Token.IsCancellationRequested) queue[item.ID] = item; @@ -134,7 +135,7 @@ private void RegisterResultsUpdatedEvent() if (e.Query.RawQuery == QueryText) // TODO: allow cancellation { PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query); - if (!_resultsUpdateQueue.Writer.TryWrite(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"); }; @@ -539,8 +540,8 @@ async Task QueryTask(PluginPair plugin) var results = await PluginManager.QueryForPlugin(plugin, query, currentCancellationToken); if (currentCancellationToken.IsCancellationRequested || results == null) return; - - if (!_resultsUpdateQueue.Writer.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken))) + + if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken))) { Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); }; diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs index be48f53c16b..87d526fd6d8 100644 --- a/Flow.Launcher/ViewModel/ResultsForUpdate.cs +++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs @@ -6,7 +6,7 @@ namespace Flow.Launcher.ViewModel { - public class ResultsForUpdate + public struct ResultsForUpdate { public List Results { get; } @@ -16,13 +16,6 @@ public class ResultsForUpdate 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 feab3a7513d..41f16f4f249 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -183,13 +183,12 @@ private void UpdateResults(List newResults, CancellationToken t 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 @@ private List NewResults(List newRawResults, string resu 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();