A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

103 lines
2.8 KiB

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Rendering
{
/// <summary>
/// Defines a default render timer that uses a standard timer.
/// </summary>
/// <remarks>
/// This class may be overridden by platform implementations to use a specialized timer
/// implementation.
/// </remarks>
public class DefaultRenderTimer : IRenderTimer
{
private IRuntimePlatform? _runtime;
private int _subscriberCount;
private Action<TimeSpan>? _tick;
private IDisposable? _subscription;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultRenderTimer"/> class.
/// </summary>
/// <param name="framesPerSecond">
/// The number of frames per second at which the loop should run.
/// </param>
public DefaultRenderTimer(int framesPerSecond)
{
FramesPerSecond = framesPerSecond;
}
/// <summary>
/// Gets the number of frames per second at which the loop runs.
/// </summary>
public int FramesPerSecond { get; }
/// <inheritdoc/>
public event Action<TimeSpan> Tick
{
add
{
_tick += value;
if (_subscriberCount++ == 0)
{
Start();
}
}
remove
{
if (--_subscriberCount == 0)
{
Stop();
}
_tick -= value;
}
}
public bool RunsInBackground => true;
/// <summary>
/// Starts the timer.
/// </summary>
protected void Start()
{
_subscription = StartCore(InternalTick);
}
/// <summary>
/// Provides the implementation of starting the timer.
/// </summary>
/// <param name="tick">The method to call on each tick.</param>
/// <remarks>
/// This can be overridden by platform implementations to use a specialized timer
/// implementation.
/// </remarks>
protected virtual IDisposable StartCore(Action<TimeSpan> tick)
{
_runtime ??= AvaloniaLocator.Current.GetRequiredService<IRuntimePlatform>();
return _runtime.StartSystemTimer(
TimeSpan.FromSeconds(1.0 / FramesPerSecond),
() => tick(TimeSpan.FromMilliseconds(Environment.TickCount)));
}
/// <summary>
/// Stops the timer.
/// </summary>
protected void Stop()
{
_subscription?.Dispose();
_subscription = null;
}
private void InternalTick(TimeSpan tickCount)
{
_tick?.Invoke(tickCount);
}
}
}