|
|
@@ -9,94 +9,69 @@ using Avalonia.Threading;
|
|
|
|
|
|
namespace Avalonia.Controls.Platform
|
|
|
{
|
|
|
- public class InternalPlatformThreadingInterface : IPlatformThreadingInterface, IRenderTimer
|
|
|
+ public class InternalPlatformThreadingInterface : IPlatformThreadingInterface
|
|
|
{
|
|
|
public InternalPlatformThreadingInterface()
|
|
|
{
|
|
|
TlsCurrentThreadIsLoopThread = true;
|
|
|
- StartTimer(
|
|
|
- DispatcherPriority.Render,
|
|
|
- new TimeSpan(0, 0, 0, 0, 66),
|
|
|
- () => Tick?.Invoke(TimeSpan.FromMilliseconds(Environment.TickCount)));
|
|
|
}
|
|
|
|
|
|
private readonly AutoResetEvent _signaled = new AutoResetEvent(false);
|
|
|
- private readonly AutoResetEvent _queued = new AutoResetEvent(false);
|
|
|
|
|
|
- private readonly Queue<Action> _actions = new Queue<Action>();
|
|
|
|
|
|
public void RunLoop(CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var handles = new[] {_signaled, _queued};
|
|
|
while (true)
|
|
|
{
|
|
|
- if (0 == WaitHandle.WaitAny(handles))
|
|
|
- Signaled?.Invoke(null);
|
|
|
- else
|
|
|
- {
|
|
|
- while (true)
|
|
|
- {
|
|
|
- Action item;
|
|
|
- lock (_actions)
|
|
|
- if (_actions.Count == 0)
|
|
|
- break;
|
|
|
- else
|
|
|
- item = _actions.Dequeue();
|
|
|
- item();
|
|
|
- }
|
|
|
- }
|
|
|
+ Signaled?.Invoke(null);
|
|
|
+ _signaled.WaitOne();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void Send(Action cb)
|
|
|
- {
|
|
|
- lock (_actions)
|
|
|
- {
|
|
|
- _actions.Enqueue(cb);
|
|
|
- _queued.Set();
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- class WatTimer : IDisposable
|
|
|
+ class TimerImpl : IDisposable
|
|
|
{
|
|
|
- private readonly IDisposable _timer;
|
|
|
+ private readonly DispatcherPriority _priority;
|
|
|
+ private readonly TimeSpan _interval;
|
|
|
+ private readonly Action _tick;
|
|
|
+ private Timer _timer;
|
|
|
private GCHandle _handle;
|
|
|
|
|
|
- public WatTimer(IDisposable timer)
|
|
|
+ public TimerImpl(DispatcherPriority priority, TimeSpan interval, Action tick)
|
|
|
{
|
|
|
- _timer = timer;
|
|
|
+ _priority = priority;
|
|
|
+ _interval = interval;
|
|
|
+ _tick = tick;
|
|
|
+ _timer = new Timer(OnTimer, null, interval, TimeSpan.FromMilliseconds(-1));
|
|
|
_handle = GCHandle.Alloc(_timer);
|
|
|
}
|
|
|
|
|
|
+ private void OnTimer(object state)
|
|
|
+ {
|
|
|
+ if (_timer == null)
|
|
|
+ return;
|
|
|
+ Dispatcher.UIThread.Post(() =>
|
|
|
+ {
|
|
|
+
|
|
|
+ if (_timer == null)
|
|
|
+ return;
|
|
|
+ _tick();
|
|
|
+ _timer?.Change(_interval, TimeSpan.FromMilliseconds(-1));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
public void Dispose()
|
|
|
{
|
|
|
_handle.Free();
|
|
|
_timer.Dispose();
|
|
|
+ _timer = null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
|
|
|
{
|
|
|
- return new WatTimer(new System.Threading.Timer(delegate
|
|
|
- {
|
|
|
- var tcs = new TaskCompletionSource<int>();
|
|
|
- Send(() =>
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- tick();
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- tcs.SetResult(0);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- tcs.Task.Wait();
|
|
|
- }, null, TimeSpan.Zero, interval));
|
|
|
-
|
|
|
-
|
|
|
+ return new TimerImpl(priority, interval, tick);
|
|
|
}
|
|
|
|
|
|
public void Signal(DispatcherPriority prio)
|