csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
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.
110 lines
3.0 KiB
110 lines
3.0 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Avalonia.Platform;
|
|
using Avalonia.Rendering;
|
|
|
|
namespace Avalonia.Controls.Platform
|
|
{
|
|
public class InternalPlatformThreadingInterface : IPlatformThreadingInterface, IRenderLoop
|
|
{
|
|
public InternalPlatformThreadingInterface()
|
|
{
|
|
TlsCurrentThreadIsLoopThread = true;
|
|
StartTimer(new TimeSpan(0, 0, 0, 0, 66), () => Tick?.Invoke(this, new EventArgs()));
|
|
}
|
|
|
|
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();
|
|
else
|
|
{
|
|
while (true)
|
|
{
|
|
Action item;
|
|
lock (_actions)
|
|
if (_actions.Count == 0)
|
|
break;
|
|
else
|
|
item = _actions.Dequeue();
|
|
item();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Send(Action cb)
|
|
{
|
|
lock (_actions)
|
|
{
|
|
_actions.Enqueue(cb);
|
|
_queued.Set();
|
|
}
|
|
}
|
|
|
|
class WatTimer : IDisposable
|
|
{
|
|
private readonly IDisposable _timer;
|
|
private GCHandle _handle;
|
|
|
|
public WatTimer(IDisposable timer)
|
|
{
|
|
_timer = timer;
|
|
_handle = GCHandle.Alloc(_timer);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_handle.Free();
|
|
_timer.Dispose();
|
|
}
|
|
}
|
|
|
|
public IDisposable StartTimer(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));
|
|
|
|
|
|
}
|
|
|
|
public void Signal()
|
|
{
|
|
_signaled.Set();
|
|
}
|
|
|
|
[ThreadStatic] private static bool TlsCurrentThreadIsLoopThread;
|
|
|
|
public bool CurrentThreadIsLoopThread => TlsCurrentThreadIsLoopThread;
|
|
public event Action Signaled;
|
|
public event EventHandler<EventArgs> Tick;
|
|
|
|
}
|
|
}
|