Use Task.Yield to avoid using Parallel.For

This commit is contained in:
张弘韬 2021-01-09 12:01:08 +08:00
parent c939924ec8
commit 92be6fd3dd

View file

@ -86,7 +86,7 @@ namespace Flow.Launcher.ViewModel
{
foreach (var pair in PluginManager.GetPluginsForInterface<IResultUpdated>())
{
var plugin = (IResultUpdated)pair.Plugin;
var plugin = (IResultUpdated) pair.Plugin;
plugin.ResultsUpdated += (s, e) =>
{
Task.Run(() =>
@ -113,25 +113,13 @@ namespace Flow.Launcher.ViewModel
}
});
SelectNextItemCommand = new RelayCommand(_ =>
{
SelectedResults.SelectNextResult();
});
SelectNextItemCommand = new RelayCommand(_ => { SelectedResults.SelectNextResult(); });
SelectPrevItemCommand = new RelayCommand(_ =>
{
SelectedResults.SelectPrevResult();
});
SelectPrevItemCommand = new RelayCommand(_ => { SelectedResults.SelectPrevResult(); });
SelectNextPageCommand = new RelayCommand(_ =>
{
SelectedResults.SelectNextPage();
});
SelectNextPageCommand = new RelayCommand(_ => { SelectedResults.SelectNextPage(); });
SelectPrevPageCommand = new RelayCommand(_ =>
{
SelectedResults.SelectPrevPage();
});
SelectPrevPageCommand = new RelayCommand(_ => { SelectedResults.SelectPrevPage(); });
SelectFirstResultCommand = new RelayCommand(_ => SelectedResults.SelectFirstResult());
@ -209,6 +197,7 @@ namespace Flow.Launcher.ViewModel
public ResultsViewModel History { get; private set; }
private string _queryText;
public string QueryText
{
get { return _queryText; }
@ -229,10 +218,12 @@ namespace Flow.Launcher.ViewModel
QueryTextCursorMovedToEnd = true;
QueryText = queryText;
}
public bool LastQuerySelected { get; set; }
public bool QueryTextCursorMovedToEnd { get; set; }
private ResultsViewModel _selectedResults;
private ResultsViewModel SelectedResults
{
get { return _selectedResults; }
@ -264,6 +255,7 @@ namespace Flow.Launcher.ViewModel
QueryText = string.Empty;
}
}
_selectedResults.Visbility = Visibility.Visible;
}
}
@ -324,7 +316,7 @@ namespace Flow.Launcher.ViewModel
var filtered = results.Where
(
r => StringMatcher.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet()
|| StringMatcher.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet()
|| StringMatcher.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet()
).ToList();
ContextMenu.AddResults(filtered, id);
}
@ -351,7 +343,7 @@ namespace Flow.Launcher.ViewModel
Title = string.Format(title, h.Query),
SubTitle = string.Format(time, h.ExecutedDateTime),
IcoPath = "Images\\history.png",
OriginQuery = new Query { RawQuery = h.Query },
OriginQuery = new Query {RawQuery = h.Query},
Action = _ =>
{
SelectedResults = Results;
@ -397,7 +389,8 @@ namespace Flow.Launcher.ViewModel
_lastQuery = query;
Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
{ // start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
{
// start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
if (currentUpdateSource == _updateSource && _isQueryRunning)
{
ProgressBarVisibility = Visibility.Visible;
@ -410,17 +403,14 @@ namespace Flow.Launcher.ViewModel
// so looping will stop once it was cancelled
Task[] tasks = new Task[plugins.Count];
var parallelOptions = new ParallelOptions { CancellationToken = currentCancellationToken };
try
{
Parallel.For(0, plugins.Count, parallelOptions, i =>
for (var i = 0; i < plugins.Count; i++)
{
if (!plugins[i].Metadata.Disabled)
{
tasks[i] = QueryTask(plugins[i], query, currentCancellationToken);
}
else tasks[i] = Task.CompletedTask; // Avoid Null
});
}
// Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first
await Task.WhenAll(tasks);
@ -434,20 +424,25 @@ namespace Flow.Launcher.ViewModel
// until the end of all querying
_isQueryRunning = false;
if (!currentCancellationToken.IsCancellationRequested)
{ // update to hidden if this is still the current query
{
// update to hidden if this is still the current query
ProgressBarVisibility = Visibility.Hidden;
}
// Local Function
async Task QueryTask(PluginPair plugin, Query query, CancellationToken token)
{
// Since it is wrapped within a Task.Run, the synchronous context is null
// Task.Yield will force it to run in ThreadPool
await Task.Yield();
var results = await PluginManager.QueryForPlugin(plugin, query, token);
if (!currentCancellationToken.IsCancellationRequested)
UpdateResultView(results, plugin.Metadata, query);
}
}, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
}, currentCancellationToken).ContinueWith(
t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
}
}
else
@ -514,6 +509,7 @@ namespace Flow.Launcher.ViewModel
}
};
}
return menu;
}
@ -559,6 +555,7 @@ namespace Flow.Launcher.ViewModel
var selected = SelectedResults == History;
return selected;
}
#region Hotkey
private void SetHotkey(string hotkeyStr, EventHandler<HotkeyEventArgs> action)
@ -577,7 +574,8 @@ namespace Flow.Launcher.ViewModel
catch (Exception)
{
string errorMsg =
string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr);
string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"),
hotkeyStr);
MessageBox.Show(errorMsg);
}
}
@ -627,7 +625,6 @@ namespace Flow.Launcher.ViewModel
{
if (!ShouldIgnoreHotkeys())
{
if (_settings.LastQueryMode == LastQueryMode.Empty)
{
ChangeQueryText(string.Empty);