Browse Source

Reverted Dispatcher.UIThread and added SingleThreadDispatcher

pull/213/head
Nikita Tsukanov 11 years ago
parent
commit
f50a2c361c
  1. 2
      src/Perspex.Application/Application.cs
  2. 1
      src/Perspex.Base/Perspex.Base.csproj
  3. 2
      src/Perspex.Base/Platform/IPclPlatformWrapper.cs
  4. 27
      src/Perspex.Base/Threading/Dispatcher.cs
  5. 2
      src/Perspex.Base/Threading/DispatcherTimer.cs
  6. 4
      src/Perspex.Base/Threading/PerspexSynchronizationContext.cs
  7. 58
      src/Perspex.Base/Threading/SingleThreadDispatcher.cs
  8. 4
      src/Perspex.Controls/TopLevel.cs
  9. 12
      src/Perspex.HtmlRenderer/HtmlControl.cs
  10. BIN
      src/Shared/PlatformSupport/PclPlatformWrapper.cs

2
src/Perspex.Application/Application.cs

@ -144,7 +144,7 @@ namespace Perspex
{
var source = new CancellationTokenSource();
closable.Closed += (s, e) => source.Cancel();
Dispatcher.MainLoop(source.Token);
Dispatcher.UIThread.MainLoop(source.Token);
}
/// <summary>

1
src/Perspex.Base/Perspex.Base.csproj

@ -75,6 +75,7 @@
<Compile Include="Threading\JobRunner.cs" />
<Compile Include="Threading\PerspexScheduler.cs" />
<Compile Include="Threading\PerspexSynchronizationContext.cs" />
<Compile Include="Threading\SingleThreadDispatcher.cs" />
<Compile Include="Utilities\MathUtilities.cs" />
<Compile Include="Utilities\TypeUtilities.cs" />
</ItemGroup>

2
src/Perspex.Base/Platform/IPclPlatformWrapper.cs

@ -10,5 +10,7 @@ namespace Perspex.Platform
public interface IPclPlatformWrapper
{
Assembly[] GetLoadedAssemblies();
void PostThreadPoolItem(Action cb);
IDisposable StartSystemTimer(TimeSpan interval, Action tick);
}
}

27
src/Perspex.Base/Threading/Dispatcher.cs

@ -15,26 +15,29 @@ namespace Perspex.Threading
/// In Perspex, there is usually only a single <see cref="Dispatcher"/> in the application -
/// the one for the UI thread, retrieved via the <see cref="UIThread"/> property.
/// </remarks>
public static class Dispatcher
public class Dispatcher
{
private static readonly JobRunner _jobRunner =
new JobRunner(PerspexLocator.Current.GetService<IPlatformThreadingInterface>());
private readonly IPlatformThreadingInterface _platform;
private readonly JobRunner _jobRunner;
/// <summary>
/// Initializes a new instance of the <see cref="Dispatcher"/> class.
/// </summary>
static Dispatcher()
public static Dispatcher UIThread { get; } =
new Dispatcher(PerspexLocator.Current.GetService<IPlatformThreadingInterface>());
public Dispatcher(IPlatformThreadingInterface platform)
{
PerspexLocator.Current.GetService<IPlatformThreadingInterface>().Signaled += _jobRunner.RunJobs;
_platform = platform;
_jobRunner = new JobRunner(platform);
_platform.Signaled += _jobRunner.RunJobs;
}
/// <summary>
/// Runs the dispatcher's main loop.
/// </summary>
/// <param name="cancellationToken">
/// A cancellation token used to exit the main loop.
/// </param>
public static void MainLoop(CancellationToken cancellationToken)
public void MainLoop(CancellationToken cancellationToken)
{
var platform = PerspexLocator.Current.GetService<IPlatformThreadingInterface>();
cancellationToken.Register(platform.Signal);
@ -44,7 +47,7 @@ namespace Perspex.Threading
/// <summary>
/// Runs continuations pushed on the loop.
/// </summary>
public static void RunJobs()
public void RunJobs()
{
_jobRunner.RunJobs();
}
@ -55,7 +58,7 @@ namespace Perspex.Threading
/// <param name="action">The method.</param>
/// <param name="priority">The priority with which to invoke the method.</param>
/// <returns>A task that can be used to track the method's execution.</returns>
public static Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
public Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
return _jobRunner.InvokeAsync(action, priority);
}
@ -65,7 +68,7 @@ namespace Perspex.Threading
/// </summary>
/// <param name="action">The method.</param>
/// <param name="priority">The priority with which to invoke the method.</param>
internal static void Post(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
internal void Post(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
_jobRunner.Post(action, priority);
}

2
src/Perspex.Base/Threading/DispatcherTimer.cs

@ -177,7 +177,7 @@ namespace Perspex.Threading
/// </summary>
private void InternalTick()
{
Dispatcher.Post(RaiseTick, _priority);
Dispatcher.UIThread.Post(RaiseTick, _priority);
}
/// <summary>

4
src/Perspex.Base/Threading/PerspexSynchronizationContext.cs

@ -36,14 +36,14 @@ namespace Perspex.Threading
/// <inheritdoc/>
public override void Post(SendOrPostCallback d, object state)
{
Dispatcher.Post(() => d(state));
Dispatcher.UIThread.Post(() => d(state));
}
/// <inheritdoc/>
public override void Send(SendOrPostCallback d, object state)
{
// TODO: Add check for being on the main thread, we should invoke the method immediately in this case
Dispatcher.InvokeAsync(() => d(state)).Wait();
Dispatcher.UIThread.InvokeAsync(() => d(state)).Wait();
}
}
}

58
src/Perspex.Base/Threading/SingleThreadDispatcher.cs

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Perspex.Platform;
namespace Perspex.Threading
{
public class SingleThreadDispatcher : Dispatcher
{
class ThreadingInterface : IPlatformThreadingInterface
{
private AutoResetEvent _evnt = new AutoResetEvent(false);
private JobRunner _timerJobRunner;
public ThreadingInterface()
{
_timerJobRunner = new JobRunner(this);
}
public void RunLoop(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
_evnt.WaitOne();
if (cancellationToken.IsCancellationRequested)
return;
Signaled?.Invoke();
_timerJobRunner.RunJobs();
}
}
public IDisposable StartTimer(TimeSpan interval, Action tick)
=> PerspexLocator.Current.GetService<IPclPlatformWrapper>().StartSystemTimer(interval,
() => _timerJobRunner.Post(tick, DispatcherPriority.Normal));
public void Signal() => _evnt.Set();
public event Action Signaled;
}
public SingleThreadDispatcher() : base(new ThreadingInterface())
{
}
public static Dispatcher StartNew(CancellationToken token)
{
var dispatcher = new SingleThreadDispatcher();
PerspexLocator.Current.GetService<IPclPlatformWrapper>().PostThreadPoolItem(() =>
{
dispatcher.MainLoop(token);
});
return dispatcher;
}
}
}

4
src/Perspex.Controls/TopLevel.cs

@ -397,7 +397,7 @@ namespace Perspex.Controls
/// </summary>
private void HandleLayoutNeeded()
{
Dispatcher.InvokeAsync(LayoutManager.ExecuteLayoutPass, DispatcherPriority.Render);
Dispatcher.UIThread.InvokeAsync(LayoutManager.ExecuteLayoutPass, DispatcherPriority.Render);
}
/// <summary>
@ -413,7 +413,7 @@ namespace Perspex.Controls
/// </summary>
private void HandleRenderNeeded()
{
Dispatcher.InvokeAsync(
Dispatcher.UIThread.InvokeAsync(
() => PlatformImpl.Invalidate(new Rect(ClientSize)),
DispatcherPriority.Render);
}

12
src/Perspex.HtmlRenderer/HtmlControl.cs

@ -563,7 +563,7 @@ namespace Perspex.Controls.Html
if (CheckAccess())
OnLoadComplete(e);
else
Dispatcher.Invoke(new Action<HtmlLinkClickedEventArgs>(OnLinkClicked), e);
Dispatcher.UIThread.Invoke(new Action<HtmlLinkClickedEventArgs>(OnLinkClicked), e);
}
@ -572,7 +572,7 @@ namespace Perspex.Controls.Html
if (CheckAccess())
OnLinkClicked(e);
else
Dispatcher.Invoke(new Action<HtmlLinkClickedEventArgs>(OnLinkClicked), e);
Dispatcher.UIThread.Invoke(new Action<HtmlLinkClickedEventArgs>(OnLinkClicked), e);
}
private void OnRenderError(object sender, HtmlRenderErrorEventArgs e)
@ -580,7 +580,7 @@ namespace Perspex.Controls.Html
if (CheckAccess())
OnRenderError(e);
else
Dispatcher.Invoke(new Action<HtmlRenderErrorEventArgs>(OnRenderError), e);
Dispatcher.UIThread.Invoke(new Action<HtmlRenderErrorEventArgs>(OnRenderError), e);
}
private void OnStylesheetLoad(object sender, HtmlStylesheetLoadEventArgs e)
@ -588,7 +588,7 @@ namespace Perspex.Controls.Html
if (CheckAccess())
OnStylesheetLoad(e);
else
Dispatcher.Invoke(new Action<HtmlStylesheetLoadEventArgs>(OnStylesheetLoad), e);
Dispatcher.UIThread.Invoke(new Action<HtmlStylesheetLoadEventArgs>(OnStylesheetLoad), e);
}
private void OnImageLoad(object sender, HtmlImageLoadEventArgs e)
@ -596,7 +596,7 @@ namespace Perspex.Controls.Html
if (CheckAccess())
OnImageLoad(e);
else
Dispatcher.Invoke(new Action<HtmlImageLoadEventArgs>(OnImageLoad), e);
Dispatcher.UIThread.Invoke(new Action<HtmlImageLoadEventArgs>(OnImageLoad), e);
}
private void OnRefresh(object sender, HtmlRefreshEventArgs e)
@ -604,7 +604,7 @@ namespace Perspex.Controls.Html
if (CheckAccess())
OnRefresh(e);
else
Dispatcher.Invoke(new Action<HtmlRefreshEventArgs>(OnRefresh), e);
Dispatcher.UIThread.Invoke(new Action<HtmlRefreshEventArgs>(OnRefresh), e);
}
*/
}

BIN
src/Shared/PlatformSupport/PclPlatformWrapper.cs

Binary file not shown.
Loading…
Cancel
Save