diff --git a/src/Main/Base/Project/Src/Services/IMessageLoop.cs b/src/Main/Base/Project/Src/Services/IMessageLoop.cs
index 728e4fce25..d8d30ff565 100644
--- a/src/Main/Base/Project/Src/Services/IMessageLoop.cs
+++ b/src/Main/Base/Project/Src/Services/IMessageLoop.cs
@@ -37,7 +37,7 @@ namespace ICSharpCode.SharpDevelop
///
/// Gets whether the current thread is different from the thread running this message loop.
///
- /// InvokeRequired = !CheckAcess()
+ /// InvokeRequired = !CheckAccess()
bool InvokeRequired { get; }
///
diff --git a/src/Main/SharpDevelop/SharpDevelop.csproj b/src/Main/SharpDevelop/SharpDevelop.csproj
index e32b238416..04a9c46a72 100644
--- a/src/Main/SharpDevelop/SharpDevelop.csproj
+++ b/src/Main/SharpDevelop/SharpDevelop.csproj
@@ -51,6 +51,7 @@
..\..\Libraries\log4net\log4net.dll
+
3.0
diff --git a/src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs b/src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs
index 25868b7c3e..d4ae37afcd 100644
--- a/src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs
+++ b/src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Windows.Interop;
-
+using System.Windows.Threading;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
@@ -79,6 +79,7 @@ namespace ICSharpCode.SharpDevelop.Workbench
MessageService.ShowException(ex);
}
}
+ StartPreloadThread();
}
NavigationService.ResumeLogging();
@@ -95,5 +96,71 @@ namespace ICSharpCode.SharpDevelop.Workbench
MessageService.ShowException(e, "Exception while saving workbench state.");
}
}
+
+ #region Preload-Thread
+ void StartPreloadThread()
+ {
+ // Wait until UI is responsive and pads are initialized before starting the thread.
+ // We don't want to slow down SharpDevelop's startup, we just want to make opening
+ // a project more responsive.
+ // (and parallelism doesn't really help here; we're mostly waiting for the disk to load the code)
+ // So we do our work in the background while the user decides which project to open.
+ SD.MainThread.InvokeAsync(
+ () => new Thread(PreloadThread) { IsBackground = true, Priority = ThreadPriority.BelowNormal }.Start(),
+ DispatcherPriority.ApplicationIdle
+ ).FireAndForget();
+ }
+
+ void PreloadThread()
+ {
+ // Pre-load some stuff to make SharpDevelop more responsive once it is started.
+ LoggingService.Debug("Preload-Thread started.");
+
+ // warm up MSBuild
+ string projectCode = @"
+
+
+ Debug
+ AnyCPU
+
+
+
+
+
+";
+ var project = new Microsoft.Build.Evaluation.Project(
+ new System.Xml.XmlTextReader(new System.IO.StringReader(projectCode)), null, "4.0",
+ new Microsoft.Build.Evaluation.ProjectCollection());
+
+ // warm up the XSHD loader
+ ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.GetDefinition("C#");
+ // warm up the C# parser
+ var parser = new ICSharpCode.NRefactory.CSharp.CSharpParser();
+ var cu = parser.Parse(new ICSharpCode.AvalonEdit.Document.TextDocument(@"using System;
+class Test {
+ int SomeMethod(string a);
+ void Main(string[] b) {
+ SomeMethod(b[0 + 1]);
+ }
+}"), "test.cs");
+ // warm up the type system
+ var parsedFile = cu.ToTypeSystem();
+ var pc = new ICSharpCode.NRefactory.CSharp.CSharpProjectContent().UpdateProjectContent(null, parsedFile);
+ pc = pc.AddAssemblyReferences(new[] { ICSharpCode.NRefactory.TypeSystem.Implementation.MinimalCorlib.Instance });
+ var compilation = pc.CreateCompilation();
+ // warm up the resolver
+ var resolver = new ICSharpCode.NRefactory.CSharp.Resolver.CSharpAstResolver(compilation, cu, parsedFile);
+ foreach (var node in cu.Descendants) {
+ resolver.Resolve(node);
+ }
+ // warm up AvalonEdit (must be done on main thread)
+ SD.MainThread.InvokeAsync(
+ delegate {
+ object editor;
+ SD.EditorControlService.CreateEditor(out editor);
+ LoggingService.Debug("Preload-Thread finished.");
+ }, DispatcherPriority.Background);
+ }
+ #endregion
}
}