mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Refactoring multithreading
1. ThreadPool -> Task 2. fix deadlock 3. remove unnecessory application.dispatcher.invoke 4. enable non-main thread access to results collection 5. Misc 6. part of #412
This commit is contained in:
parent
923f4ed045
commit
d536377329
15 changed files with 146 additions and 140 deletions
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
|
@ -144,7 +145,7 @@ namespace Wox.Plugin.PluginManagement
|
|||
string filePath = Path.Combine(folder, Guid.NewGuid().ToString() + ".wox");
|
||||
|
||||
context.API.StartLoadingBar();
|
||||
ThreadPool.QueueUserWorkItem(delegate
|
||||
Task.Run(() =>
|
||||
{
|
||||
using (WebClient Client = new WebClient())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wox.Infrastructure.Logger;
|
||||
|
||||
namespace Wox.Plugin.Program
|
||||
|
|
@ -40,7 +41,7 @@ namespace Wox.Plugin.Program
|
|||
{
|
||||
if (!isIndexing)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
Programs.IndexPrograms();
|
||||
isIndexing = false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ namespace Wox.Plugin.Program
|
|||
private void ReIndexing()
|
||||
{
|
||||
programSourceView.Items.Refresh();
|
||||
ThreadPool.QueueUserWorkItem(t =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Visible; });
|
||||
Programs.IndexPrograms();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Newtonsoft.Json;
|
||||
using Wox.Infrastructure.Exception;
|
||||
|
|
@ -55,17 +56,14 @@ namespace Wox.Core.Plugin
|
|||
}
|
||||
else
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
string actionReponse = ExecuteCallback(result1.JsonRPCAction);
|
||||
JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject<JsonRPCRequestModel>(actionReponse);
|
||||
if (jsonRpcRequestModel != null
|
||||
&& !String.IsNullOrEmpty(jsonRpcRequestModel.Method)
|
||||
&& jsonRpcRequestModel.Method.StartsWith("Wox."))
|
||||
{
|
||||
string actionReponse = ExecuteCallback(result1.JsonRPCAction);
|
||||
JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject<JsonRPCRequestModel>(actionReponse);
|
||||
if (jsonRpcRequestModel != null
|
||||
&& !String.IsNullOrEmpty(jsonRpcRequestModel.Method)
|
||||
&& jsonRpcRequestModel.Method.StartsWith("Wox."))
|
||||
{
|
||||
ExecuteWoxAPI(jsonRpcRequestModel.Method.Substring(4), jsonRpcRequestModel.Parameters);
|
||||
}
|
||||
});
|
||||
ExecuteWoxAPI(jsonRpcRequestModel.Method.Substring(4), jsonRpcRequestModel.Parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
return !result1.JsonRPCAction.DontHideAfterAction;
|
||||
|
|
@ -126,7 +124,7 @@ namespace Wox.Core.Plugin
|
|||
{
|
||||
using (Process process = Process.Start(startInfo))
|
||||
{
|
||||
if (process != null)
|
||||
if (process != null)
|
||||
{
|
||||
using (StreamReader reader = process.StandardOutput)
|
||||
{
|
||||
|
|
@ -152,7 +150,7 @@ namespace Wox.Core.Plugin
|
|||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new WoxJsonRPCException(e.Message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Wox.Infrastructure.Exception;
|
||||
using Wox.Infrastructure.Logger;
|
||||
|
|
@ -11,8 +13,8 @@ namespace Wox.Core.Plugin
|
|||
|
||||
internal abstract class PluginConfig
|
||||
{
|
||||
private const string pluginConfigName = "plugin.json";
|
||||
private static List<PluginMetadata> pluginMetadatas = new List<PluginMetadata>();
|
||||
private const string PluginConfigName = "plugin.json";
|
||||
private static readonly List<PluginMetadata> PluginMetadatas = new List<PluginMetadata>();
|
||||
|
||||
/// <summary>
|
||||
/// Parse plugin metadata in giving directories
|
||||
|
|
@ -21,45 +23,41 @@ namespace Wox.Core.Plugin
|
|||
/// <returns></returns>
|
||||
public static List<PluginMetadata> Parse(string[] pluginDirectories)
|
||||
{
|
||||
pluginMetadatas.Clear();
|
||||
foreach (string pluginDirectory in pluginDirectories)
|
||||
{
|
||||
ParsePluginConfigs(pluginDirectory);
|
||||
}
|
||||
|
||||
return pluginMetadatas;
|
||||
PluginMetadatas.Clear();
|
||||
var directories = pluginDirectories.SelectMany(Directory.GetDirectories);
|
||||
ParsePluginConfigs(directories);
|
||||
return PluginMetadatas;
|
||||
}
|
||||
|
||||
private static void ParsePluginConfigs(string pluginDirectory)
|
||||
private static void ParsePluginConfigs(IEnumerable<string> directories)
|
||||
{
|
||||
if (!Directory.Exists(pluginDirectory)) return;
|
||||
|
||||
string[] directories = Directory.GetDirectories(pluginDirectory);
|
||||
foreach (string directory in directories)
|
||||
Parallel.ForEach(directories, directory =>
|
||||
{
|
||||
if (File.Exists((Path.Combine(directory, "NeedDelete.txt"))))
|
||||
if (File.Exists(Path.Combine(directory, "NeedDelete.txt")))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(directory, true);
|
||||
continue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal(e);
|
||||
}
|
||||
}
|
||||
PluginMetadata metadata = GetPluginMetadata(directory);
|
||||
if (metadata != null)
|
||||
else
|
||||
{
|
||||
pluginMetadatas.Add(metadata);
|
||||
PluginMetadata metadata = GetPluginMetadata(directory);
|
||||
if (metadata != null)
|
||||
{
|
||||
PluginMetadatas.Add(metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static PluginMetadata GetPluginMetadata(string pluginDirectory)
|
||||
{
|
||||
string configPath = Path.Combine(pluginDirectory, pluginConfigName);
|
||||
string configPath = Path.Combine(pluginDirectory, PluginConfigName);
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
Log.Warn($"parse plugin {configPath} failed: didn't find config file.");
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wox.Core.Resource;
|
||||
using Wox.Core.UserSettings;
|
||||
using Wox.Infrastructure;
|
||||
|
|
@ -31,7 +32,7 @@ namespace Wox.Core.Plugin
|
|||
public static IPublicAPI API { private set; get; }
|
||||
private static PluginsSettings _settings;
|
||||
private static List<PluginMetadata> _metadatas;
|
||||
private static readonly string[] Directories = {Infrastructure.Wox.PreinstalledDirectory, Infrastructure.Wox.UserDirectory };
|
||||
private static readonly string[] Directories = { Infrastructure.Wox.PreinstalledDirectory, Infrastructure.Wox.UserDirectory };
|
||||
|
||||
private static void ValidateUserDirectory()
|
||||
{
|
||||
|
|
@ -69,43 +70,36 @@ namespace Wox.Core.Plugin
|
|||
ResourceMerger.UpdatePluginLanguages();
|
||||
|
||||
API = api;
|
||||
foreach (PluginPair pluginPair in AllPlugins)
|
||||
Parallel.ForEach(AllPlugins, pair =>
|
||||
{
|
||||
PluginPair pair = pluginPair;
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
var milliseconds = Stopwatch.Normal($"Plugin init: {pair.Metadata.Name}", () =>
|
||||
{
|
||||
var milliseconds = Stopwatch.Normal($"Plugin init: {pair.Metadata.Name}", () =>
|
||||
pair.Plugin.Init(new PluginInitContext
|
||||
{
|
||||
pair.Plugin.Init(new PluginInitContext
|
||||
{
|
||||
CurrentPluginMetadata = pair.Metadata,
|
||||
Proxy = HttpProxy.Instance,
|
||||
API = API
|
||||
});
|
||||
CurrentPluginMetadata = pair.Metadata,
|
||||
Proxy = HttpProxy.Instance,
|
||||
API = API
|
||||
});
|
||||
pair.InitTime = milliseconds;
|
||||
InternationalizationManager.Instance.UpdatePluginMetadataTranslations(pair);
|
||||
});
|
||||
}
|
||||
pair.InitTime = milliseconds;
|
||||
InternationalizationManager.Instance.UpdatePluginMetadataTranslations(pair);
|
||||
});
|
||||
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
|
||||
foreach (var plugin in AllPlugins)
|
||||
{
|
||||
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
|
||||
foreach (var plugin in AllPlugins)
|
||||
if (IsGlobalPlugin(plugin.Metadata))
|
||||
{
|
||||
if (IsGlobalPlugin(plugin.Metadata))
|
||||
GlobalPlugins.Add(plugin);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string actionKeyword in plugin.Metadata.ActionKeywords)
|
||||
{
|
||||
GlobalPlugins.Add(plugin);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string actionKeyword in plugin.Metadata.ActionKeywords)
|
||||
{
|
||||
NonGlobalPlugins[actionKeyword] = plugin;
|
||||
}
|
||||
NonGlobalPlugins[actionKeyword] = plugin;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Wox.Core.Plugin
|
|||
public const string Python = "python";
|
||||
public const string PythonExecutable = "pythonw.exe";
|
||||
|
||||
public static IEnumerable<PluginPair> CSharpPlugins(IEnumerable<PluginMetadata> source)
|
||||
public static IEnumerable<PluginPair> CSharpPlugins(List<PluginMetadata> source)
|
||||
{
|
||||
var plugins = new List<PluginPair>();
|
||||
var metadatas = source.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp);
|
||||
|
|
@ -63,7 +63,7 @@ namespace Wox.Core.Plugin
|
|||
return plugins;
|
||||
}
|
||||
|
||||
public static IEnumerable<PluginPair> PythonPlugins(IEnumerable<PluginMetadata> source, string pythonDirecotry)
|
||||
public static IEnumerable<PluginPair> PythonPlugins(List<PluginMetadata> source, string pythonDirecotry)
|
||||
{
|
||||
var metadatas = source.Where(o => o.Language.ToUpper() == AllowedLanguage.Python);
|
||||
string filename;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using NAppUpdate.Framework;
|
||||
using NAppUpdate.Framework.Common;
|
||||
|
|
@ -80,7 +81,7 @@ namespace Wox.Core.Updater
|
|||
|
||||
public void CheckUpdate()
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
string json = HttpRequest.Get(VersionCheckURL, HttpProxy.Instance);
|
||||
if (!string.IsNullOrEmpty(json))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using Exceptionless;
|
||||
|
|
@ -40,7 +41,7 @@ namespace Wox.CrashReporter
|
|||
private void SendReport()
|
||||
{
|
||||
Hide();
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
string reproduceSteps = new TextRange(tbReproduceSteps.Document.ContentStart, tbReproduceSteps.Document.ContentEnd).Text;
|
||||
exception.ToExceptionless()
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ namespace Wox.Infrastructure.Image
|
|||
img.Freeze();
|
||||
ImageSources[icon] = img;
|
||||
}
|
||||
Task.Factory.StartNew(() =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
Stopwatch.Debug("Preload images from cache", () =>
|
||||
{
|
||||
|
|
|
|||
3
Wox.sln
3
Wox.sln
|
|
@ -86,6 +86,9 @@ EndProject
|
|||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PreSolutionBuild", "PreSolutionBuild\PreSolutionBuild.vcxproj", "{88731DA8-C020-476E-B79A-3ADEF65ACA9F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using NHotkey;
|
||||
using NHotkey.Wpf;
|
||||
using Wox.Core.Plugin;
|
||||
|
|
@ -139,7 +139,10 @@ namespace Wox
|
|||
o.PluginID = plugin.ID;
|
||||
o.OriginQuery = query;
|
||||
});
|
||||
MainVM.UpdateResultView(results, plugin, query);
|
||||
Task.Run(() =>
|
||||
{
|
||||
MainVM.UpdateResultView(results, plugin, query);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Wox
|
|||
InitializeComponent();
|
||||
_settings = settings;
|
||||
_api = api;
|
||||
ResultListBoxPreview.DataContext = new ResultsViewModel(_settings, null);
|
||||
ResultListBoxPreview.DataContext = new ResultsViewModel(_settings);
|
||||
Loaded += Setting_Loaded;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,11 +86,15 @@ namespace Wox.ViewModel
|
|||
{
|
||||
foreach (var pair in PluginManager.GetPluginsForInterface<IResultUpdated>())
|
||||
{
|
||||
var plugin = (IResultUpdated) pair.Plugin;
|
||||
var plugin = (IResultUpdated)pair.Plugin;
|
||||
plugin.ResultsUpdated += (s, e) =>
|
||||
{
|
||||
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
|
||||
UpdateResultView(e.Results, pair.Metadata, e.Query);
|
||||
Task.Run(() =>
|
||||
{
|
||||
|
||||
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
|
||||
UpdateResultView(e.Results, pair.Metadata, e.Query);
|
||||
}, _updateToken);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -202,7 +206,10 @@ namespace Wox.ViewModel
|
|||
menus.Add(ContextMenuPluginInfo(id));
|
||||
|
||||
ContextMenu.Clear();
|
||||
ContextMenu.AddResults(menus, id);
|
||||
Task.Run(() =>
|
||||
{
|
||||
ContextMenu.AddResults(menus, id);
|
||||
}, _updateToken);
|
||||
ContextMenuVisibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
|
|
@ -219,14 +226,14 @@ namespace Wox.ViewModel
|
|||
|
||||
private void InitializeResultListBox()
|
||||
{
|
||||
Results = new ResultsViewModel(_settings, _topMostRecord);
|
||||
Results = new ResultsViewModel(_settings);
|
||||
ResultListBoxVisibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
|
||||
private void InitializeContextMenu()
|
||||
{
|
||||
ContextMenu = new ResultsViewModel(_settings, _topMostRecord);
|
||||
ContextMenu = new ResultsViewModel(_settings);
|
||||
ContextMenuVisibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
|
|
@ -413,7 +420,10 @@ namespace Wox.ViewModel
|
|||
}
|
||||
}
|
||||
ContextMenu.Clear();
|
||||
ContextMenu.AddResults(filterResults, contextMenuId);
|
||||
Task.Run(() =>
|
||||
{
|
||||
ContextMenu.AddResults(filterResults, contextMenuId);
|
||||
}, _updateToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -455,18 +465,20 @@ namespace Wox.ViewModel
|
|||
}, _updateToken);
|
||||
|
||||
var plugins = PluginManager.ValidPluginsForQuery(query);
|
||||
foreach (var plugin in plugins)
|
||||
Task.Run(() =>
|
||||
{
|
||||
var config = _settings.PluginSettings.Plugins[plugin.Metadata.ID];
|
||||
if (!config.Disabled)
|
||||
Parallel.ForEach(plugins, plugin =>
|
||||
{
|
||||
Task.Factory.StartNew(() =>
|
||||
var config = _settings.PluginSettings.Plugins[plugin.Metadata.ID];
|
||||
if (!config.Disabled)
|
||||
{
|
||||
|
||||
var results = PluginManager.QueryForPlugin(plugin, query);
|
||||
UpdateResultView(results, plugin.Metadata, query);
|
||||
}, _updateToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, _updateToken);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -478,11 +490,6 @@ namespace Wox.ViewModel
|
|||
_queryHistory.Reset();
|
||||
}
|
||||
|
||||
private void UpdateResultViewInternal(List<Result> list, PluginMetadata metadata)
|
||||
{
|
||||
Results.AddResults(list, metadata.ID);
|
||||
}
|
||||
|
||||
private void DisplayQueryHistory(HistoryItem history)
|
||||
{
|
||||
if (history != null)
|
||||
|
|
@ -495,21 +502,23 @@ namespace Wox.ViewModel
|
|||
var executeQueryHistoryTitle = InternationalizationManager.Instance.GetTranslation("executeQuery");
|
||||
var lastExecuteTime = InternationalizationManager.Instance.GetTranslation("lastExecuteTime");
|
||||
Results.RemoveResultsExcept(historyMetadata);
|
||||
UpdateResultViewInternal(new List<Result>
|
||||
var result = new Result
|
||||
{
|
||||
new Result
|
||||
Title = string.Format(executeQueryHistoryTitle, history.Query),
|
||||
SubTitle = string.Format(lastExecuteTime, history.ExecutedDateTime),
|
||||
IcoPath = "Images\\history.png",
|
||||
PluginDirectory = Infrastructure.Wox.ProgramPath,
|
||||
Action = _ =>
|
||||
{
|
||||
Title = string.Format(executeQueryHistoryTitle,history.Query),
|
||||
SubTitle = string.Format(lastExecuteTime,history.ExecutedDateTime),
|
||||
IcoPath = "Images\\history.png",
|
||||
PluginDirectory = Infrastructure.Wox.ProgramPath,
|
||||
Action = _ =>{
|
||||
QueryText = history.Query;
|
||||
OnTextBoxSelected();
|
||||
return false;
|
||||
}
|
||||
QueryText = history.Query;
|
||||
OnTextBoxSelected();
|
||||
return false;
|
||||
}
|
||||
}, historyMetadata);
|
||||
};
|
||||
Task.Run(() =>
|
||||
{
|
||||
Results.AddResults(new List<Result> { result }, historyMetadata.ID);
|
||||
}, _updateToken);
|
||||
}
|
||||
}
|
||||
private Result ContextMenuTopMost(Result result)
|
||||
|
|
@ -583,21 +592,29 @@ namespace Wox.ViewModel
|
|||
_topMostRecordStorage.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To avoid deadlock, this method should not called from main thread
|
||||
/// </summary>
|
||||
public void UpdateResultView(List<Result> list, PluginMetadata metadata, Query originQuery)
|
||||
{
|
||||
_queryHasReturn = true;
|
||||
ProgressBarVisibility = Visibility.Hidden;
|
||||
|
||||
list.ForEach(o =>
|
||||
foreach (var result in list)
|
||||
{
|
||||
o.Score += _userSelectedRecord.GetSelectedCount(o) * 5;
|
||||
});
|
||||
if (_topMostRecord.IsTopMost(result))
|
||||
{
|
||||
result.Score = int.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Score += _userSelectedRecord.GetSelectedCount(result) * 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (originQuery.RawQuery == _lastQuery.RawQuery)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
UpdateResultViewInternal(list, metadata);
|
||||
});
|
||||
Results.AddResults(list, metadata.ID);
|
||||
}
|
||||
|
||||
if (list.Count > 0 && !ResultListBoxVisibility.IsVisible())
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ using System.Collections.ObjectModel;
|
|||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using Wox.Core.UserSettings;
|
||||
using Wox.Plugin;
|
||||
using Wox.Storage;
|
||||
|
|
@ -16,17 +18,18 @@ namespace Wox.ViewModel
|
|||
#region Private Fields
|
||||
|
||||
private ResultViewModel _selectedResult;
|
||||
public ResultCollection Results { get; } = new ResultCollection();
|
||||
public ResultCollection Results { get; }
|
||||
private Thickness _margin;
|
||||
|
||||
private readonly object _resultsUpdateLock = new object();
|
||||
private Settings _settings;
|
||||
private TopMostRecord _topMostRecord;
|
||||
private readonly object _addResultsLock = new object();
|
||||
private readonly object _collectionLock = new object();
|
||||
private readonly Settings _settings;
|
||||
|
||||
public ResultsViewModel(Settings settings, TopMostRecord topMostRecord)
|
||||
public ResultsViewModel(Settings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
_topMostRecord = topMostRecord;
|
||||
Results = new ResultCollection();
|
||||
BindingOperations.EnableCollectionSynchronization(Results, _collectionLock);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -81,11 +84,6 @@ namespace Wox.ViewModel
|
|||
|
||||
#region Private Methods
|
||||
|
||||
private bool IsTopMostResult(Result result)
|
||||
{
|
||||
return _topMostRecord.IsTopMost(result);
|
||||
}
|
||||
|
||||
private int InsertIndexOf(int newScore, IList<ResultViewModel> list)
|
||||
{
|
||||
int index = 0;
|
||||
|
|
@ -181,45 +179,35 @@ namespace Wox.ViewModel
|
|||
|
||||
public void RemoveResultsExcept(PluginMetadata metadata)
|
||||
{
|
||||
lock (_resultsUpdateLock)
|
||||
{
|
||||
Results.RemoveAll(r => r.RawResult.PluginID != metadata.ID);
|
||||
}
|
||||
Results.RemoveAll(r => r.RawResult.PluginID != metadata.ID);
|
||||
}
|
||||
|
||||
public void RemoveResultsFor(PluginMetadata metadata)
|
||||
{
|
||||
lock (_resultsUpdateLock)
|
||||
{
|
||||
Results.RemoveAll(r => r.PluginID == metadata.ID);
|
||||
}
|
||||
Results.RemoveAll(r => r.PluginID == metadata.ID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To avoid deadlock, this method should not called from main thread
|
||||
/// </summary>
|
||||
public void AddResults(List<Result> newRawResults, string resultId)
|
||||
{
|
||||
lock (_resultsUpdateLock)
|
||||
lock (_addResultsLock)
|
||||
{
|
||||
var newResults = newRawResults.Select(r => new ResultViewModel(r)).ToList();
|
||||
// todo use async to do new result calculation
|
||||
var resultsCopy = Results.ToList();
|
||||
var oldResults = resultsCopy.Where(r => r.PluginID == resultId).ToList();
|
||||
|
||||
// intersection of A (old results) and B (new newResults)
|
||||
var intersection = oldResults.Intersect(newResults).ToList();
|
||||
|
||||
// remove result of relative complement of B in A
|
||||
foreach (var result in oldResults.Except(intersection))
|
||||
{
|
||||
resultsCopy.Remove(result);
|
||||
}
|
||||
|
||||
// update scores
|
||||
foreach (var result in newResults)
|
||||
{
|
||||
if (IsTopMostResult(result.RawResult))
|
||||
{
|
||||
result.Score = int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
// update index for result in intersection of A and B
|
||||
foreach (var commonResult in intersection)
|
||||
{
|
||||
|
|
@ -300,6 +288,7 @@ namespace Wox.ViewModel
|
|||
ResultViewModel newResult = newItems[i];
|
||||
if (!oldResult.Equals(newResult))
|
||||
{
|
||||
|
||||
this[i] = newResult;
|
||||
}
|
||||
else if (oldResult.Score != newResult.Score)
|
||||
|
|
@ -308,6 +297,7 @@ namespace Wox.ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (newCount > oldCount)
|
||||
{
|
||||
for (int i = oldCount; i < newCount; i++)
|
||||
|
|
@ -323,7 +313,6 @@ namespace Wox.ViewModel
|
|||
RemoveAt(removeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue