diff --git a/src/Eto.DevExtension.LanguageServer/Eto.DevExtension.LanguageServer.csproj b/src/Eto.DevExtension.LanguageServer/Eto.DevExtension.LanguageServer.csproj
index 12b66aa..fe49ca9 100644
--- a/src/Eto.DevExtension.LanguageServer/Eto.DevExtension.LanguageServer.csproj
+++ b/src/Eto.DevExtension.LanguageServer/Eto.DevExtension.LanguageServer.csproj
@@ -24,11 +24,6 @@
-
-
-
-
-
diff --git a/src/Eto.DevExtension.VisualStudio.Windows/Editor/EtoPreviewPane.cs b/src/Eto.DevExtension.VisualStudio.Windows/Editor/EtoPreviewPane.cs
index 0c6c1f4..f265729 100644
--- a/src/Eto.DevExtension.VisualStudio.Windows/Editor/EtoPreviewPane.cs
+++ b/src/Eto.DevExtension.VisualStudio.Windows/Editor/EtoPreviewPane.cs
@@ -125,6 +125,7 @@ void RegisterIndependentView(bool subscribe)
public EtoPreviewPane(EtoAddinPackage package, string fileName, IVsTextLines textBuffer, string projectKey, CodeEditorHost codeEditor)
: base(package)
{
+ ThreadHelper.ThrowIfNotOnUIThread();
this.editor = codeEditor;
this.package = package;
this.textBuffer = textBuffer;
@@ -138,6 +139,7 @@ public EtoPreviewPane(EtoAddinPackage package, string fileName, IVsTextLines tex
host.ProjectChanged += PreviewHost_ProjectChanged;
var designHost = new RemoteDesignPanel(async request =>
{
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var snapshot = documentBuffer?.CurrentSnapshot;
var result = await host.RenderAsync(request, await ProjectAssemblyPaths.GetAsync(fileName));
if (snapshot != null && !disposed)
@@ -163,7 +165,11 @@ public EtoPreviewPane(EtoAddinPackage package, string fileName, IVsTextLines tex
};
preview = previewSplitter.Preview;
PreviewLayoutSettings.Load(previewSplitter);
- previewSplitter.LayoutChanged += (sender, e) => PreviewLayoutSettings.Save(previewSplitter);
+ previewSplitter.LayoutChanged += (sender, e) =>
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+ PreviewLayoutSettings.Save(previewSplitter);
+ };
platformDropDown = new DropDown { ToolTip = "Platform to draw the preview with" };
platformDropDown.SelectedKeyChanged += PlatformDropDown_SelectedKeyChanged;
@@ -307,7 +313,7 @@ protected override void Initialize()
// the document may not be registered yet while the frame is being created
if (!LockDocument())
- ThreadHelper.JoinableTaskFactory.StartOnIdle(() => LockDocument());
+ _ = ThreadHelper.JoinableTaskFactory.StartOnIdle(() => LockDocument());
preview.Update();
}
@@ -581,7 +587,11 @@ public override int LoadUIState(Stream stateStream)
public int GetViewClassID(out Guid pclsidView) => editor.codeWindow.GetViewClassID(out pclsidView);
public int SetBaseEditorCaption(string[] pszBaseEditorCaption) => editor.codeWindow.SetBaseEditorCaption(pszBaseEditorCaption);
public int GetEditorCaption(READONLYSTATUS dwReadOnly, out string pbstrEditorCaption) => editor.codeWindow.GetEditorCaption(dwReadOnly, out pbstrEditorCaption);
- public int Close() => editor.Close();
+ public int Close()
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+ return editor.Close();
+ }
public int GetLastActiveView(out IVsTextView ppView) => editor.codeWindow.GetLastActiveView(out ppView);
int IVsCodeWindowEx.Initialize(uint grfCodeWindowBehaviorFlags, VSUSERCONTEXTATTRIBUTEUSAGE usageAuxUserContext, string szNameAuxUserContext, string szValueAuxUserContext, uint InitViewFlags, INITVIEW[] pInitView) => ((IVsCodeWindowEx)editor.codeWindow).Initialize(grfCodeWindowBehaviorFlags, usageAuxUserContext, szNameAuxUserContext, szValueAuxUserContext, InitViewFlags, pInitView);
diff --git a/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewHostClient.cs b/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewHostClient.cs
index 982f158..bf852ba 100644
--- a/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewHostClient.cs
+++ b/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewHostClient.cs
@@ -1,5 +1,6 @@
using Eto.Designer;
using Eto.Drawing;
+using Microsoft.VisualStudio.Shell;
using Newtonsoft.Json.Linq;
using StreamJsonRpc;
using System;
@@ -71,6 +72,8 @@ public async Task RenderAsync(PreviewRenderRequest request,
await requestLock.WaitAsync();
try
{
+ // the platform and theme choices are read from VS settings
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
// a second try covers a host that exited after a rebuild, or that serves an older build
var wanted = await PreviewPlatforms.ResolveAsync();
var theme = PreviewPlatforms.ThemeChoice;
diff --git a/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewPlatforms.cs b/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewPlatforms.cs
index 96a4dd4..0e1bedc 100644
--- a/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewPlatforms.cs
+++ b/src/Eto.DevExtension.VisualStudio.Windows/Editor/PreviewPlatforms.cs
@@ -86,9 +86,14 @@ public static List GetAvailable()
/// A platform id or , remembered for each solution. Use on the UI thread.
public static string Choice
{
- get => GetChoice(CollectionPath, Auto, unsavedChoice);
+ get
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+ return GetChoice(CollectionPath, Auto, unsavedChoice);
+ }
set
{
+ ThreadHelper.ThrowIfNotOnUIThread();
if (SetChoice(CollectionPath, value ?? Auto, Auto, ref unsavedChoice))
ChoiceChanged?.Invoke(null, EventArgs.Empty);
}
@@ -97,9 +102,14 @@ public static string Choice
/// A theme name from the host, or , remembered for each solution. Use on the UI thread.
public static string ThemeChoice
{
- get => GetChoice(ThemeCollectionPath, DefaultTheme, unsavedTheme);
+ get
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+ return GetChoice(ThemeCollectionPath, DefaultTheme, unsavedTheme);
+ }
set
{
+ ThreadHelper.ThrowIfNotOnUIThread();
if (SetChoice(ThemeCollectionPath, value ?? DefaultTheme, DefaultTheme, ref unsavedTheme))
ThemeChoiceChanged?.Invoke(null, EventArgs.Empty);
}
diff --git a/src/Eto.DevExtension.VisualStudio.Windows/Wizards/WindowTitleBar.cs b/src/Eto.DevExtension.VisualStudio.Windows/Wizards/WindowTitleBar.cs
index a9f169e..6c11cac 100644
--- a/src/Eto.DevExtension.VisualStudio.Windows/Wizards/WindowTitleBar.cs
+++ b/src/Eto.DevExtension.VisualStudio.Windows/Wizards/WindowTitleBar.cs
@@ -1,4 +1,6 @@
using Microsoft.VisualStudio.PlatformUI;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Threading;
using System;
using System.Runtime.InteropServices;
using System.Windows;
@@ -23,7 +25,16 @@ static class WindowTitleBar
public static void Attach(Window window)
{
void Apply() => ApplyTheme(window);
- void ThemeChanged(ThemeChangedEventArgs e) => window.Dispatcher.BeginInvoke((Action)Apply);
+ void ThemeChanged(ThemeChangedEventArgs e)
+ {
+ // may be raised off the UI thread
+ var factory = EtoAddinPackage.Instance?.JoinableTaskFactory ?? ThreadHelper.JoinableTaskFactory;
+ factory.RunAsync(async () =>
+ {
+ await factory.SwitchToMainThreadAsync();
+ Apply();
+ }).Task.Forget();
+ }
if (new WindowInteropHelper(window).Handle != IntPtr.Zero)
Apply();