diff --git a/src/Perspex.Application/Application.cs b/src/Perspex.Application/Application.cs
index 1b94ecaa51..40c3542d8c 100644
--- a/src/Perspex.Application/Application.cs
+++ b/src/Perspex.Application/Application.cs
@@ -150,6 +150,7 @@ namespace Perspex
///
protected virtual void RegisterServices()
{
+ PerspexSynchronizationContext.InstallIfNeeded();
this.FocusManager = new FocusManager();
this.InputManager = new InputManager();
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/Threading/Dispatcher.cs b/src/Perspex.Base/Threading/Dispatcher.cs
index 31191d587c..d959151543 100644
--- a/src/Perspex.Base/Threading/Dispatcher.cs
+++ b/src/Perspex.Base/Threading/Dispatcher.cs
@@ -68,5 +68,15 @@ namespace Perspex.Threading
{
return this.mainLoop.InvokeAsync(action, priority);
}
+
+ ///
+ /// Post action that will be invoked on main thread
+ ///
+ /// The method.
+ /// The priority with which to invoke the method.
+ internal void Post(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
+ {
+ this.mainLoop.Post(action, priority);
+ }
}
}
\ No newline at end of file
diff --git a/src/Perspex.Base/Threading/DispatcherTimer.cs b/src/Perspex.Base/Threading/DispatcherTimer.cs
index 73335ea408..0d49bb21f8 100644
--- a/src/Perspex.Base/Threading/DispatcherTimer.cs
+++ b/src/Perspex.Base/Threading/DispatcherTimer.cs
@@ -203,7 +203,7 @@ namespace Perspex.Threading
///
private void InternalTick()
{
- this.Dispatcher.InvokeAsync(this.RaiseTick, this.priority);
+ this.Dispatcher.Post(this.RaiseTick, this.priority);
}
///
diff --git a/src/Perspex.Base/Threading/MainLoop.cs b/src/Perspex.Base/Threading/MainLoop.cs
index 009d331b28..3a99133d15 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,29 @@ 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.
+ ///
+ /// The priority with which to invoke the method.
+ internal void Post(Action action, DispatcherPriority priority)
+ {
+ this.AddJob(new Job(action, priority, 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 +134,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