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