diff --git a/src/Android/Avalonia.Android/ChoreographerTimer.cs b/src/Android/Avalonia.Android/ChoreographerTimer.cs index 4c6d176539..06ec9a9cd6 100644 --- a/src/Android/Avalonia.Android/ChoreographerTimer.cs +++ b/src/Android/Avalonia.Android/ChoreographerTimer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Android.OS; @@ -7,16 +8,16 @@ using Android.Views; using Avalonia.Reactive; using Avalonia.Rendering; - -using Java.Lang; +using ThreadPriority = System.Threading.ThreadPriority; namespace Avalonia.Android { internal sealed class ChoreographerTimer : Java.Lang.Object, IRenderTimer, Choreographer.IFrameCallback { private readonly object _lock = new(); - - private readonly Thread _thread; + + private AutoResetEvent _event = new(false); + private long _lastTime; private readonly TaskCompletionSource _choreographer = new(); private readonly ISet _views = new HashSet(); @@ -26,8 +27,14 @@ namespace Avalonia.Android public ChoreographerTimer() { - _thread = new Thread(Loop); - _thread.Start(); + new Thread(Loop) + { + Priority = ThreadPriority.AboveNormal + }.Start(); + new Thread(RenderLoop) + { + Priority = ThreadPriority.AboveNormal + }.Start(); } public bool RunsInBackground => true; @@ -86,17 +93,32 @@ namespace Avalonia.Android _choreographer.SetResult(Choreographer.Instance!); Looper.Loop(); } + + private void RenderLoop() + { + while (true) + { + _event.WaitOne(); + long time; + lock (_lock) + { + time = _lastTime; + } + _tick?.Invoke(TimeSpan.FromTicks(time / 100)); + } + } + public void DoFrame(long frameTimeNanos) { - _tick?.Invoke(TimeSpan.FromTicks(frameTimeNanos / 100)); - lock (_lock) { if (_count > 0 && _views.Count > 0) { Choreographer.Instance!.PostFrameCallback(this); } + _lastTime = frameTimeNanos; + _event.Set(); } } }