fix #189 startup is too slow

This commit is contained in:
qianlifeng 2014-10-27 15:08:32 +08:00
parent 3634ca624d
commit 07ed6a6416
3 changed files with 2 additions and 150 deletions

View File

@ -1,145 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Wox.Helper
{
/// <summary>
/// Provides a caller-friendly wrapper around parallel actions.
/// http://stackoverflow.com/a/540380
/// </summary>
public sealed class Forker
{
int running;
private readonly object joinLock = new object(), eventLock = new object();
/// <summary>Raised when all operations have completed.</summary>
public event EventHandler AllComplete
{
add { lock (eventLock) { allComplete += value; } }
remove { lock (eventLock) { allComplete -= value; } }
}
private EventHandler allComplete;
/// <summary>Raised when each operation completes.</summary>
public event EventHandler<ParallelEventArgs> ItemComplete
{
add { lock (eventLock) { itemComplete += value; } }
remove { lock (eventLock) { itemComplete -= value; } }
}
private EventHandler<ParallelEventArgs> itemComplete;
private void OnItemComplete(object state, Exception exception)
{
EventHandler<ParallelEventArgs> itemHandler = itemComplete; // don't need to lock
if (itemHandler != null) itemHandler(this, new ParallelEventArgs(state, exception));
if (Interlocked.Decrement(ref running) == 0)
{
EventHandler allHandler = allComplete; // don't need to lock
if (allHandler != null) allHandler(this, EventArgs.Empty);
lock (joinLock)
{
Monitor.PulseAll(joinLock);
}
}
}
/// <summary>Adds a callback to invoke when each operation completes.</summary>
/// <returns>Current instance (for fluent API).</returns>
public Forker OnItemComplete(EventHandler<ParallelEventArgs> handler)
{
if (handler == null) throw new ArgumentNullException("handler");
ItemComplete += handler;
return this;
}
/// <summary>Adds a callback to invoke when all operations are complete.</summary>
/// <returns>Current instance (for fluent API).</returns>
public Forker OnAllComplete(EventHandler handler)
{
if (handler == null) throw new ArgumentNullException("handler");
AllComplete += handler;
return this;
}
/// <summary>Waits for all operations to complete.</summary>
public void Join()
{
Join(-1);
}
/// <summary>Waits (with timeout) for all operations to complete.</summary>
/// <returns>Whether all operations had completed before the timeout.</returns>
public bool Join(int millisecondsTimeout)
{
lock (joinLock)
{
if (CountRunning() == 0) return true;
Thread.SpinWait(1); // try our luck...
return (CountRunning() == 0) ||
Monitor.Wait(joinLock, millisecondsTimeout);
}
}
/// <summary>Indicates the number of incomplete operations.</summary>
/// <returns>The number of incomplete operations.</returns>
public int CountRunning()
{
return Interlocked.CompareExchange(ref running, 0, 0);
}
/// <summary>Enqueues an operation.</summary>
/// <param name="action">The operation to perform.</param>
/// <returns>The current instance (for fluent API).</returns>
public Forker Fork(ThreadStart action) { return Fork(action, null); }
/// <summary>Enqueues an operation.</summary>
/// <param name="action">The operation to perform.</param>
/// <param name="state">An opaque object, allowing the caller to identify operations.</param>
/// <returns>The current instance (for fluent API).</returns>
public Forker Fork(ThreadStart action, object state)
{
if (action == null) throw new ArgumentNullException("action");
Interlocked.Increment(ref running);
ThreadPool.QueueUserWorkItem(delegate
{
Exception exception = null;
try
{
action();
}
catch (Exception ex)
{
exception = ex;
#if (DEBUG)
{
throw;
}
#endif
}
OnItemComplete(state, exception);
});
return this;
}
/// <summary>Event arguments representing the completion of a parallel action.</summary>
public class ParallelEventArgs : EventArgs
{
private readonly object state;
private readonly Exception exception;
internal ParallelEventArgs(object state, Exception exception)
{
this.state = state;
this.exception = exception;
}
/// <summary>The opaque state object that identifies the action (null otherwise).</summary>
public object State { get { return state; } }
/// <summary>The exception thrown by the parallel action, or null if it completed without exception.</summary>
public Exception Exception { get { return exception; } }
}
}
}

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using Wox.Helper; using Wox.Helper;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
@ -20,19 +21,16 @@ namespace Wox.PluginLoader
plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas)); plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas));
plugins.AddRange(new BasePluginLoader<PythonPlugin>().LoadPlugin(pluginMetadatas)); plugins.AddRange(new BasePluginLoader<PythonPlugin>().LoadPlugin(pluginMetadatas));
Forker forker = new Forker();
foreach (PluginPair pluginPair in plugins) foreach (PluginPair pluginPair in plugins)
{ {
PluginPair pair = pluginPair; PluginPair pair = pluginPair;
forker.Fork(() => pair.Plugin.Init(new PluginInitContext() ThreadPool.QueueUserWorkItem(o => pair.Plugin.Init(new PluginInitContext()
{ {
CurrentPluginMetadata = pair.Metadata, CurrentPluginMetadata = pair.Metadata,
Proxy = HttpProxy.Instance, Proxy = HttpProxy.Instance,
API = App.Window API = App.Window
})); }));
} }
forker.Join();
} }
public static List<PluginPair> AllPlugins public static List<PluginPair> AllPlugins

View File

@ -129,7 +129,6 @@
<DependentUpon>WPFErrorReportingDialog.xaml</DependentUpon> <DependentUpon>WPFErrorReportingDialog.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Helper\FontHelper.cs" /> <Compile Include="Helper\FontHelper.cs" />
<Compile Include="Helper\Forker.cs" />
<Compile Include="Helper\HttpProxy.cs" /> <Compile Include="Helper\HttpProxy.cs" />
<Compile Include="Helper\ImageLoader.cs" /> <Compile Include="Helper\ImageLoader.cs" />
<Compile Include="Helper\SingleInstance.cs" /> <Compile Include="Helper\SingleInstance.cs" />