Browse Source

Fixed DispatcherTimer's priorities

pull/1196/head
Nikita Tsukanov 9 years ago
parent
commit
bdbe95b9b1
  1. 2
      src/Android/Avalonia.Android/AndroidThreadingInterface.cs
  2. 3
      src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
  3. 13
      src/Avalonia.Base/Threading/Dispatcher.cs
  4. 18
      src/Avalonia.Base/Threading/DispatcherTimer.cs
  5. 6
      src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
  6. 6
      src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
  7. 4
      src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs
  8. 2
      src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs
  9. 2
      src/Windows/Avalonia.Win32/Win32Platform.cs
  10. 2
      src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs
  11. 2
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs
  12. 2
      tests/Avalonia.RenderTests/TestBase.cs

2
src/Android/Avalonia.Android/AndroidThreadingInterface.cs

@ -30,7 +30,7 @@ namespace Avalonia.Android
return; return;
} }
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{ {
if (interval.TotalMilliseconds < 10) if (interval.TotalMilliseconds < 10)
interval = TimeSpan.FromMilliseconds(10); interval = TimeSpan.FromMilliseconds(10);

3
src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs

@ -17,10 +17,11 @@ namespace Avalonia.Platform
/// <summary> /// <summary>
/// Starts a timer. /// Starts a timer.
/// </summary> /// </summary>
/// <param name="priority"></param>
/// <param name="interval">The interval.</param> /// <param name="interval">The interval.</param>
/// <param name="tick">The action to call on each tick.</param> /// <param name="tick">The action to call on each tick.</param>
/// <returns>An <see cref="IDisposable"/> used to stop the timer.</returns> /// <returns>An <see cref="IDisposable"/> used to stop the timer.</returns>
IDisposable StartTimer(TimeSpan interval, Action tick); IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick);
void Signal(DispatcherPriority priority); void Signal(DispatcherPriority priority);

13
src/Avalonia.Base/Threading/Dispatcher.cs

@ -84,6 +84,19 @@ namespace Avalonia.Threading
_jobRunner?.Post(action, priority); _jobRunner?.Post(action, priority);
} }
/// <summary>
/// This is needed for platform backends that don't have internal priority system (e. g. win32)
/// To ensure that there are no jobs with higher priority
/// </summary>
/// <param name="currentPriority"></param>
internal void EnsurePriority(DispatcherPriority currentPriority)
{
if (currentPriority == DispatcherPriority.MaxValue)
return;
currentPriority += 1;
_jobRunner.RunJobs(currentPriority);
}
/// <summary> /// <summary>
/// Allows unit tests to change the platform threading interface. /// Allows unit tests to change the platform threading interface.
/// </summary> /// </summary>

18
src/Avalonia.Base/Threading/DispatcherTimer.cs

@ -17,13 +17,11 @@ namespace Avalonia.Threading
private readonly DispatcherPriority _priority; private readonly DispatcherPriority _priority;
private TimeSpan _interval; private TimeSpan _interval;
private readonly Action _raiseTickAction;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DispatcherTimer"/> class. /// Initializes a new instance of the <see cref="DispatcherTimer"/> class.
/// </summary> /// </summary>
public DispatcherTimer() : this(DispatcherPriority.Normal) public DispatcherTimer() : this(DispatcherPriority.Background)
{ {
} }
@ -34,7 +32,6 @@ namespace Avalonia.Threading
public DispatcherTimer(DispatcherPriority priority) public DispatcherTimer(DispatcherPriority priority)
{ {
_priority = priority; _priority = priority;
_raiseTickAction = RaiseTick;
} }
/// <summary> /// <summary>
@ -187,7 +184,7 @@ namespace Avalonia.Threading
throw new Exception("Could not start timer: IPlatformThreadingInterface is not registered."); throw new Exception("Could not start timer: IPlatformThreadingInterface is not registered.");
} }
_timer = threading.StartTimer(Interval, InternalTick); _timer = threading.StartTimer(_priority, Interval, InternalTick);
} }
} }
@ -210,14 +207,7 @@ namespace Avalonia.Threading
/// </summary> /// </summary>
private void InternalTick() private void InternalTick()
{ {
Dispatcher.UIThread.InvokeAsync(_raiseTickAction, _priority); Dispatcher.UIThread.EnsurePriority(_priority);
}
/// <summary>
/// Raises the <see cref="Tick"/> event.
/// </summary>
private void RaiseTick()
{
Tick?.Invoke(this, EventArgs.Empty); Tick?.Invoke(this, EventArgs.Empty);
} }
} }

6
src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs

@ -70,15 +70,13 @@ namespace Avalonia.Gtk3
Native.GtkMainIteration(); Native.GtkMainIteration();
} }
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{ {
var msec = interval.TotalMilliseconds; var msec = interval.TotalMilliseconds;
if (msec <= 0)
throw new ArgumentException("Don't know how to create a timer with zero or negative interval");
var imsec = (uint) msec; var imsec = (uint) msec;
if (imsec == 0) if (imsec == 0)
imsec = 1; imsec = 1;
return GlibTimeout.StarTimer(imsec, tick); return GlibTimeout.StartTimer(GlibPriority.FromDispatcherPriority(priority), imsec, tick);
} }
private bool[] _signaled = new bool[(int) DispatcherPriority.MaxValue + 1]; private bool[] _signaled = new bool[(int) DispatcherPriority.MaxValue + 1];

6
src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs

@ -48,12 +48,10 @@ namespace Avalonia.Gtk3.Interop
} }
} }
public static IDisposable StarTimer(uint interval, Action tick) public static IDisposable StartTimer(int priority, uint interval, Action tick)
{ {
if (interval == 0)
throw new ArgumentException("Don't know how to create a timer with zero or negative interval");
var timer = new Timer (); var timer = new Timer ();
GlibTimeout.Add(GlibPriority.FromDispatcherPriority(DispatcherPriority.Normal), interval, GlibTimeout.Add(priority, interval,
() => () =>
{ {
if (timer.Stopped) if (timer.Stopped)

4
src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs

@ -17,7 +17,7 @@ namespace Avalonia.LinuxFramebuffer
public PlatformThreadingInterface() public PlatformThreadingInterface()
{ {
TlsCurrentThreadIsLoopThread = true; TlsCurrentThreadIsLoopThread = true;
StartTimer(new TimeSpan(0, 0, 0, 0, 66), () => Tick?.Invoke(this, new EventArgs())); StartTimer(DispatcherPriority.Render, new TimeSpan(0, 0, 0, 0, 66), () => Tick?.Invoke(this, new EventArgs()));
} }
private readonly AutoResetEvent _signaled = new AutoResetEvent(false); private readonly AutoResetEvent _signaled = new AutoResetEvent(false);
@ -74,7 +74,7 @@ namespace Avalonia.LinuxFramebuffer
} }
} }
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{ {
return new WatTimer(new System.Threading.Timer(delegate return new WatTimer(new System.Threading.Timer(delegate
{ {

2
src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs

@ -16,7 +16,7 @@ namespace Avalonia.MonoMac
public event Action<DispatcherPriority?> Signaled; public event Action<DispatcherPriority?> Signaled;
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
=> NSTimer.CreateRepeatingScheduledTimer(interval, () => tick()); => NSTimer.CreateRepeatingScheduledTimer(interval, () => tick());
public void Signal(DispatcherPriority prio) public void Signal(DispatcherPriority prio)

2
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -114,7 +114,7 @@ namespace Avalonia.Win32
} }
} }
public IDisposable StartTimer(TimeSpan interval, Action callback) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action callback)
{ {
UnmanagedMethods.TimerProc timerDelegate = UnmanagedMethods.TimerProc timerDelegate =
(hWnd, uMsg, nIDEvent, dwTime) => callback(); (hWnd, uMsg, nIDEvent, dwTime) => callback();

2
src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs

@ -51,7 +51,7 @@ namespace Avalonia.iOS
} }
}*/ }*/
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
=> NSTimer.CreateRepeatingScheduledTimer(interval, _ => tick()); => NSTimer.CreateRepeatingScheduledTimer(interval, _ => tick());
public void Signal(DispatcherPriority prio) public void Signal(DispatcherPriority prio)

2
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs

@ -160,7 +160,7 @@ namespace Avalonia.Base.UnitTests
throw new NotImplementedException(); throw new NotImplementedException();
} }
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

2
tests/Avalonia.RenderTests/TestBase.cs

@ -161,7 +161,7 @@ namespace Avalonia.Direct2D1.RenderTests
throw new NotImplementedException(); throw new NotImplementedException();
} }
public IDisposable StartTimer(TimeSpan interval, Action tick) public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

Loading…
Cancel
Save