real async plugin loading

This commit is contained in:
Paddy Xu
2017-06-04 17:26:07 +03:00
parent 86733a4d3d
commit 8bfedfc21d
4 changed files with 55 additions and 63 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.Windows.Forms;
using System.Windows.Threading;
namespace QuickLook
{
@@ -25,7 +26,8 @@ namespace QuickLook
if (e.Modifiers != Keys.None)
return;
ViewWindowManager.GetInstance().InvokeRoutine(e);
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => ViewWindowManager.GetInstance().InvokeRoutine(e)),
DispatcherPriority.ApplicationIdle);
}
private void InstallKeyHook(KeyEventHandler handler)

View File

@@ -16,9 +16,6 @@ namespace QuickLook
/// </summary>
public partial class MainWindowTransparent : Window
{
private string _path = string.Empty;
private IViewer _plugin;
internal MainWindowTransparent()
{
// this object should be initialized before loading UI components, because many of which are binding to it.
@@ -43,18 +40,21 @@ namespace QuickLook
ViewWindowManager.GetInstance().RunAndClosePreview();
}
public string PreviewPath { get; private set; }
public IViewer Plugin { get; private set; }
public ContextObject ContextObject { get; private set; }
internal void RunAndHide()
{
if (string.IsNullOrEmpty(_path))
if (string.IsNullOrEmpty(PreviewPath))
return;
try
{
Process.Start(new ProcessStartInfo(_path)
Process.Start(new ProcessStartInfo(PreviewPath)
{
WorkingDirectory = Path.GetDirectoryName(_path)
WorkingDirectory = Path.GetDirectoryName(PreviewPath)
});
}
catch (Exception e)
@@ -96,21 +96,21 @@ namespace QuickLook
ContextObject.Reset();
_plugin?.Cleanup();
_plugin = null;
Plugin?.Cleanup();
Plugin = null;
ProcessHelper.PerformAggressiveGC();
}
internal void BeginShow(IViewer matchedPlugin, string path)
internal void BeginShow(IViewer matchedPlugin, string path, Action<ExceptionDispatchInfo> exceptionHandler)
{
_path = path;
_plugin = matchedPlugin;
PreviewPath = path;
Plugin = matchedPlugin;
ContextObject.ViewerWindow = this;
// get window size before showing it
_plugin.Prepare(path, ContextObject);
Plugin.Prepare(path, ContextObject);
SetOpenWithButtonAndPath();
@@ -129,31 +129,27 @@ namespace QuickLook
//WindowHelper.SetActivate(new WindowInteropHelper(this), ContextObject.CanFocus);
// load plugin, do not block UI
Exception thrown = null;
Dispatcher.BeginInvoke(new Action(() =>
{
try
{
_plugin.View(path, ContextObject);
Plugin.View(path, ContextObject);
}
catch (Exception e)
{
thrown = e;
exceptionHandler(ExceptionDispatchInfo.Capture(e));
}
}),
DispatcherPriority.Render).Wait();
if (thrown != null)
ExceptionDispatchInfo.Capture(thrown).Throw();
DispatcherPriority.Input);
}
private void SetOpenWithButtonAndPath()
{
var isExe = FileHelper.GetAssocApplication(_path, out string appFriendlyName);
var isExe = FileHelper.GetAssocApplication(PreviewPath, out string appFriendlyName);
buttonOpenWith.Content = isExe == null
? Directory.Exists(_path)
? $"Browse “{Path.GetFileName(_path)}”"
? Directory.Exists(PreviewPath)
? $"Browse “{Path.GetFileName(PreviewPath)}”"
: "Open..."
: isExe == true
? $"Run “{appFriendlyName}”"

View File

@@ -4,7 +4,6 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using QuickLook.ExtensionMethods;
using QuickLook.Plugin;
using QuickLook.Plugin.InfoPanel;

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Runtime.ExceptionServices;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
using QuickLook.Helpers;
using QuickLook.Plugin;
@@ -123,8 +124,8 @@ namespace QuickLook
private void SwitchPreviewRemoteInvoke(HeartbeatEventArgs e)
{
// sleep for 1.5s
if (e.InvokeTick - _lastSwitchTick < 1.5 * TimeSpan.TicksPerSecond)
// sleep for 0.6s
if (e.InvokeTick - _lastSwitchTick < 0.6 * TimeSpan.TicksPerSecond)
return;
if (e.FocusedFile == _path)
@@ -135,7 +136,7 @@ namespace QuickLook
if (string.IsNullOrEmpty(e.FocusedFile))
return;
_currentMainWindow?.Dispatcher.Invoke(() => SwitchPreview());
_currentMainWindow?.Dispatcher.BeginInvoke(new Action(SwitchPreview), DispatcherPriority.ApplicationIdle);
}
private void RunFocusMonitor()
@@ -158,26 +159,24 @@ namespace QuickLook
internal bool InvokeViewer(string path = null)
{
if (path == null)
path = _path;
if (path != null)
_path = path;
if (string.IsNullOrEmpty(path))
if (string.IsNullOrEmpty(_path))
return false;
if (!Directory.Exists(path) && !File.Exists(path))
if (!Directory.Exists(_path) && !File.Exists(_path))
return false;
RunFocusMonitor();
var matchedPlugin = PluginManager.GetInstance().FindMatch(path);
var matchedPlugin = PluginManager.GetInstance().FindMatch(_path);
BeginShowNewWindow(matchedPlugin, path);
BeginShowNewWindow(matchedPlugin);
return true;
}
private void BeginShowNewWindow(IViewer matchedPlugin, string path)
{
try
private void BeginShowNewWindow(IViewer matchedPlugin)
{
_currentMainWindow.UnloadPlugin();
@@ -189,28 +188,24 @@ namespace QuickLook
if (!ReferenceEquals(oldWindow, _currentMainWindow))
oldWindow.BeginHide();
_currentMainWindow.BeginShow(matchedPlugin, path);
_currentMainWindow.BeginShow(matchedPlugin, _path, CurrentPluginFailed);
}
catch (Exception e) // if current plugin failed, switch to default one.
private void CurrentPluginFailed(ExceptionDispatchInfo e)
{
var plugin = _currentMainWindow.Plugin.GetType();
_currentMainWindow.BeginHide();
TrayIconManager.GetInstance().ShowNotification("", $"Failed to preview {Path.GetFileName(path)}", true);
TrayIconManager.GetInstance().ShowNotification("", $"Failed to preview {Path.GetFileName(_path)}", true);
Debug.WriteLine(e.ToString());
Debug.WriteLine(e.StackTrace);
Debug.WriteLine(e.SourceException.StackTrace);
if (matchedPlugin != PluginManager.GetInstance().DefaultPlugin)
{
matchedPlugin.Cleanup();
matchedPlugin = PluginManager.GetInstance().DefaultPlugin;
BeginShowNewWindow(matchedPlugin, path);
}
if (plugin != PluginManager.GetInstance().DefaultPlugin.GetType())
BeginShowNewWindow(PluginManager.GetInstance().DefaultPlugin);
else
{
ExceptionDispatchInfo.Capture(e).Throw();
}
}
e.Throw();
}
internal static ViewWindowManager GetInstance()