diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs
index 2e5b2902f4..77dfc60b83 100644
--- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs
+++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs
@@ -30,7 +30,7 @@ namespace Avalonia.Android
return;
}
- public IDisposable StartTimer(TimeSpan interval, Action tick)
+ public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{
if (interval.TotalMilliseconds < 10)
interval = TimeSpan.FromMilliseconds(10);
diff --git a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
index 68f9e2c631..9f5417ca95 100644
--- a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
+++ b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
@@ -17,10 +17,11 @@ namespace Avalonia.Platform
///
/// Starts a timer.
///
+ ///
/// The interval.
/// The action to call on each tick.
/// An used to stop the timer.
- IDisposable StartTimer(TimeSpan interval, Action tick);
+ IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick);
void Signal(DispatcherPriority priority);
diff --git a/src/Avalonia.Base/Threading/Dispatcher.cs b/src/Avalonia.Base/Threading/Dispatcher.cs
index a60b663bed..a4b1aaafbc 100644
--- a/src/Avalonia.Base/Threading/Dispatcher.cs
+++ b/src/Avalonia.Base/Threading/Dispatcher.cs
@@ -84,6 +84,19 @@ namespace Avalonia.Threading
_jobRunner?.Post(action, priority);
}
+ ///
+ /// 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
+ ///
+ ///
+ internal void EnsurePriority(DispatcherPriority currentPriority)
+ {
+ if (currentPriority == DispatcherPriority.MaxValue)
+ return;
+ currentPriority += 1;
+ _jobRunner.RunJobs(currentPriority);
+ }
+
///
/// Allows unit tests to change the platform threading interface.
///
diff --git a/src/Avalonia.Base/Threading/DispatcherTimer.cs b/src/Avalonia.Base/Threading/DispatcherTimer.cs
index 972fdb2049..4a8a9d673f 100644
--- a/src/Avalonia.Base/Threading/DispatcherTimer.cs
+++ b/src/Avalonia.Base/Threading/DispatcherTimer.cs
@@ -17,13 +17,11 @@ namespace Avalonia.Threading
private readonly DispatcherPriority _priority;
private TimeSpan _interval;
-
- private readonly Action _raiseTickAction;
-
+
///
/// Initializes a new instance of the class.
///
- public DispatcherTimer() : this(DispatcherPriority.Normal)
+ public DispatcherTimer() : this(DispatcherPriority.Background)
{
}
@@ -34,7 +32,6 @@ namespace Avalonia.Threading
public DispatcherTimer(DispatcherPriority priority)
{
_priority = priority;
- _raiseTickAction = RaiseTick;
}
///
@@ -187,7 +184,7 @@ namespace Avalonia.Threading
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
///
private void InternalTick()
{
- Dispatcher.UIThread.InvokeAsync(_raiseTickAction, _priority);
- }
-
- ///
- /// Raises the event.
- ///
- private void RaiseTick()
- {
+ Dispatcher.UIThread.EnsurePriority(_priority);
Tick?.Invoke(this, EventArgs.Empty);
}
}
diff --git a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
index 10405037ab..aefd873155 100644
--- a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
+++ b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
@@ -70,15 +70,13 @@ namespace Avalonia.Gtk3
Native.GtkMainIteration();
}
- public IDisposable StartTimer(TimeSpan interval, Action tick)
+ public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{
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;
if (imsec == 0)
imsec = 1;
- return GlibTimeout.StarTimer(imsec, tick);
+ return GlibTimeout.StartTimer(GlibPriority.FromDispatcherPriority(priority), imsec, tick);
}
private bool[] _signaled = new bool[(int) DispatcherPriority.MaxValue + 1];
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs b/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
index 5253be5afb..0ab4ef980c 100644
--- a/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
+++ b/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 ();
- GlibTimeout.Add(GlibPriority.FromDispatcherPriority(DispatcherPriority.Normal), interval,
+ GlibTimeout.Add(priority, interval,
() =>
{
if (timer.Stopped)
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs b/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs
index 3aef6944af..e6d21fca36 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs
@@ -17,7 +17,7 @@ namespace Avalonia.LinuxFramebuffer
public PlatformThreadingInterface()
{
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);
@@ -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
{
diff --git a/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs b/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs
index 80c854f5a5..184416e77a 100644
--- a/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs
+++ b/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs
@@ -16,7 +16,7 @@ namespace Avalonia.MonoMac
public event Action Signaled;
- public IDisposable StartTimer(TimeSpan interval, Action tick)
+ public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
=> NSTimer.CreateRepeatingScheduledTimer(interval, () => tick());
public void Signal(DispatcherPriority prio)
diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs
index a260efd9b9..e265749249 100644
--- a/src/Windows/Avalonia.Win32/Win32Platform.cs
+++ b/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 =
(hWnd, uMsg, nIDEvent, dwTime) => callback();
diff --git a/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs b/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs
index 6d6a5e22ca..43a620cccd 100644
--- a/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs
+++ b/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());
public void Signal(DispatcherPriority prio)
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs
index 229a34643d..09aedbdf9c 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs
@@ -160,7 +160,7 @@ namespace Avalonia.Base.UnitTests
throw new NotImplementedException();
}
- public IDisposable StartTimer(TimeSpan interval, Action tick)
+ public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{
throw new NotImplementedException();
}
diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs
index 409870ed0f..84860eefdb 100644
--- a/tests/Avalonia.RenderTests/TestBase.cs
+++ b/tests/Avalonia.RenderTests/TestBase.cs
@@ -161,7 +161,7 @@ namespace Avalonia.Direct2D1.RenderTests
throw new NotImplementedException();
}
- public IDisposable StartTimer(TimeSpan interval, Action tick)
+ public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
{
throw new NotImplementedException();
}