diff --git a/src/Perspex.Application/Application.cs b/src/Perspex.Application/Application.cs
index 1b94ecaa51..d3d8119af8 100644
--- a/src/Perspex.Application/Application.cs
+++ b/src/Perspex.Application/Application.cs
@@ -55,7 +55,7 @@ namespace Perspex
{
throw new InvalidOperationException("Cannot create more than one Application instance.");
}
-
+ PerspexSynchronizationContext.InstallIfNeeded();
Current = this;
}
diff --git a/src/Perspex.Base/Perspex.Base.csproj b/src/Perspex.Base/Perspex.Base.csproj
index 654fbb3926..d5723e5a6d 100644
--- a/src/Perspex.Base/Perspex.Base.csproj
+++ b/src/Perspex.Base/Perspex.Base.csproj
@@ -72,6 +72,7 @@
+
diff --git a/src/Perspex.Base/PerspexObject.cs b/src/Perspex.Base/PerspexObject.cs
index 0c0e402c36..ffa0b89f13 100644
--- a/src/Perspex.Base/PerspexObject.cs
+++ b/src/Perspex.Base/PerspexObject.cs
@@ -4,6 +4,8 @@
//
// -----------------------------------------------------------------------
+using Perspex.Threading;
+
namespace Perspex
{
using System;
@@ -100,6 +102,7 @@ namespace Perspex
///
public PerspexObject()
{
+ PerspexSynchronizationContext.InstallIfNeeded();
this.propertyLog = Log.ForContext(new[]
{
new PropertyEnricher("Area", "Property"),
diff --git a/src/Perspex.Base/Threading/Dispatcher.cs b/src/Perspex.Base/Threading/Dispatcher.cs
index 31191d587c..e9b91f9ab9 100644
--- a/src/Perspex.Base/Threading/Dispatcher.cs
+++ b/src/Perspex.Base/Threading/Dispatcher.cs
@@ -68,5 +68,14 @@ namespace Perspex.Threading
{
return this.mainLoop.InvokeAsync(action, priority);
}
+
+ ///
+ /// Post action that will be invoked on main thread
+ ///
+ /// The method.
+ internal void Post(Action action)
+ {
+ this.mainLoop.Post(action);
+ }
}
}
\ No newline at end of file
diff --git a/src/Perspex.Base/Threading/MainLoop.cs b/src/Perspex.Base/Threading/MainLoop.cs
index 009d331b28..b4941118ae 100644
--- a/src/Perspex.Base/Threading/MainLoop.cs
+++ b/src/Perspex.Base/Threading/MainLoop.cs
@@ -70,14 +70,21 @@ namespace Perspex.Win32.Threading
break;
}
- try
+ if (job.TaskCompletionSource == null)
{
job.Action();
- job.TaskCompletionSource.SetResult(null);
}
- catch (Exception e)
+ else
{
- job.TaskCompletionSource.SetException(e);
+ try
+ {
+ job.Action();
+ job.TaskCompletionSource.SetResult(null);
+ }
+ catch (Exception e)
+ {
+ job.TaskCompletionSource.SetException(e);
+ }
}
job = null;
@@ -92,15 +99,27 @@ namespace Perspex.Win32.Threading
/// A task that can be used to track the method's execution.
public Task InvokeAsync(Action action, DispatcherPriority priority)
{
- var job = new Job(action, priority);
+ var job = new Job(action, priority, false);
+ this.AddJob(job);
+ return job.TaskCompletionSource.Task;
+ }
+ ///
+ /// Post action that will be invoked on main thread
+ ///
+ /// The method.
+ internal void Post(Action action)
+ {
+ this.AddJob(new Job(action, DispatcherPriority.Normal, true));
+ }
+
+ private void AddJob(Job job)
+ {
lock (this.queue)
{
- this.queue.Add(job, priority);
+ this.queue.Add(job, job.Priority);
}
-
platform.Wake();
- return job.TaskCompletionSource.Task;
}
///
@@ -113,11 +132,12 @@ namespace Perspex.Win32.Threading
///
/// The method to call.
/// The job priority.
- public Job(Action action, DispatcherPriority priority)
+ /// Do not wrap excepption in TaskCompletionSource
+ public Job(Action action, DispatcherPriority priority, bool throwOnUiThread)
{
this.Action = action;
this.Priority = priority;
- this.TaskCompletionSource = new TaskCompletionSource