Try to respect DispatcherPriority when possible

This commit is contained in:
Nikita Tsukanov 2017-09-30 17:20:40 +03:00
Родитель c3e36e9339
Коммит b963d68668
23 изменённых файлов: 161 добавлений и 156 удалений

Просмотреть файл

@ -12,6 +12,7 @@ using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Platform;
using Avalonia.Threading;
namespace Avalonia.Android
{
@ -78,13 +79,13 @@ namespace Avalonia.Android
private void EnsureInvokeOnMainThread(Action action) => _handler.Post(action);
public void Signal()
public void Signal(DispatcherPriority prio)
{
EnsureInvokeOnMainThread(() => Signaled?.Invoke());
EnsureInvokeOnMainThread(() => Signaled?.Invoke(null));
}
public bool CurrentThreadIsLoopThread => Looper.MainLooper.Thread.Equals(Java.Lang.Thread.CurrentThread());
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Threading;
using Avalonia.Threading;
namespace Avalonia.Platform
{
@ -21,10 +22,10 @@ namespace Avalonia.Platform
/// <returns>An <see cref="IDisposable"/> used to stop the timer.</returns>
IDisposable StartTimer(TimeSpan interval, Action tick);
void Signal();
void Signal(DispatcherPriority priority);
bool CurrentThreadIsLoopThread { get; }
event Action Signaled;
event Action<DispatcherPriority?> Signaled;
}
}

Просмотреть файл

@ -36,7 +36,7 @@ namespace Avalonia.Threading
/// <inheritdoc/>
public override void Post(SendOrPostCallback d, object state)
{
Dispatcher.UIThread.InvokeAsync(() => d(state));
Dispatcher.UIThread.InvokeAsync(() => d(state), DispatcherPriority.Send);
}
/// <inheritdoc/>
@ -45,7 +45,7 @@ namespace Avalonia.Threading
if (Dispatcher.UIThread.CheckAccess())
d(state);
else
Dispatcher.UIThread.InvokeTaskAsync(() => d(state)).Wait();
Dispatcher.UIThread.InvokeTaskAsync(() => d(state), DispatcherPriority.Send).Wait();
}
}
}

Просмотреть файл

@ -60,7 +60,7 @@ namespace Avalonia.Threading
public void MainLoop(CancellationToken cancellationToken)
{
var platform = AvaloniaLocator.Current.GetService<IPlatformThreadingInterface>();
cancellationToken.Register(platform.Signal);
cancellationToken.Register(() => platform.Signal(DispatcherPriority.Send));
platform.RunLoop(cancellationToken);
}
@ -69,7 +69,7 @@ namespace Avalonia.Threading
/// </summary>
public void RunJobs()
{
_jobRunner?.RunJobs();
_jobRunner?.RunJobs(null);
}
/// <inheritdoc/>

Просмотреть файл

@ -9,11 +9,7 @@ namespace Avalonia.Threading
// TODO: These are copied from WPF - many won't apply to Avalonia.
public enum DispatcherPriority
{
/// <summary>
/// The job will not be processed.
/// </summary>
Inactive = 0,
MinValue = 1,
/// <summary>
/// The job will be processed when the system is idle.
/// </summary>
@ -63,5 +59,6 @@ namespace Avalonia.Threading
/// The job will be processed before other asynchronous operations.
/// </summary>
Send = 10,
MaxValue = 10
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Platform;
@ -13,29 +14,45 @@ namespace Avalonia.Threading
/// </summary>
internal class JobRunner
{
private readonly Queue<Job> _queue = new Queue<Job>();
private IPlatformThreadingInterface _platform;
private Queue<Job>[] _queues = Enumerable.Range(0, (int) DispatcherPriority.MaxValue + 1)
.Select(_ => new Queue<Job>()).ToArray();
public JobRunner(IPlatformThreadingInterface platform)
{
_platform = platform;
}
Job GetNextJob(DispatcherPriority minimumPriority)
{
for (int c = (int) DispatcherPriority.MaxValue; c >= (int) minimumPriority; c--)
{
var q = _queues[c];
lock (q)
{
if (q.Count > 0)
return q.Dequeue();
}
}
return null;
}
/// <summary>
/// Runs continuations pushed on the loop.
/// </summary>
public void RunJobs()
/// <param name="priority">Priority to execute jobs for. Pass null if platform doesn't have internal priority system</param>
public void RunJobs(DispatcherPriority? priority)
{
var minimumPriority = priority ?? DispatcherPriority.MinValue;
while (true)
{
Job job;
lock (_queue)
{
if (_queue.Count == 0)
return;
job = _queue.Dequeue();
}
var job = GetNextJob(minimumPriority);
if (job == null)
return;
if (job.TaskCompletionSource == null)
{
@ -77,7 +94,6 @@ namespace Avalonia.Threading
/// <param name="priority">The priority with which to invoke the method.</param>
internal void Post(Action action, DispatcherPriority priority)
{
// TODO: Respect priority.
AddJob(new Job(action, priority, true));
}
@ -92,13 +108,14 @@ namespace Avalonia.Threading
private void AddJob(Job job)
{
var needWake = false;
lock (_queue)
var queue = _queues[(int) job.Priority];
lock (queue)
{
needWake = _queue.Count == 0;
_queue.Enqueue(job);
needWake = queue.Count == 0;
queue.Enqueue(job);
}
if (needWake)
_platform?.Signal();
_platform?.Signal(job.Priority);
}
/// <summary>

Просмотреть файл

@ -1,60 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Threading
{
public class SingleThreadDispatcher : Dispatcher
{
class ThreadingInterface : IPlatformThreadingInterface
{
private readonly AutoResetEvent _evnt = new AutoResetEvent(false);
private readonly JobRunner _timerJobRunner;
public ThreadingInterface()
{
_timerJobRunner = new JobRunner(this);
}
public void RunLoop(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
_evnt.WaitOne();
if (cancellationToken.IsCancellationRequested)
return;
Signaled?.Invoke();
_timerJobRunner.RunJobs();
}
}
public IDisposable StartTimer(TimeSpan interval, Action tick)
=> AvaloniaLocator.Current.GetService<IRuntimePlatform>().StartSystemTimer(interval,
() => _timerJobRunner.Post(tick, DispatcherPriority.Normal));
public void Signal() => _evnt.Set();
//TODO: Actually perform a check
public bool CurrentThreadIsLoopThread => true;
public event Action Signaled;
}
public SingleThreadDispatcher() : base(new ThreadingInterface())
{
}
public static Dispatcher StartNew(CancellationToken token)
{
var dispatcher = new SingleThreadDispatcher();
AvaloniaLocator.Current.GetService<IRuntimePlatform>().PostThreadPoolItem(() =>
{
dispatcher.MainLoop(token);
});
return dispatcher;
}
}
}

Просмотреть файл

@ -165,7 +165,7 @@ namespace Avalonia.Controls.Primitives
if (increaseButton != null)
{
increaseButton.Arrange(new Rect(0, firstHeight + thumbHeight, finalSize.Width, remaining - firstHeight));
increaseButton.Arrange(new Rect(0, firstHeight + thumbHeight, finalSize.Width, Math.Max(remaining - firstHeight, 0)));
}
}

Просмотреть файл

@ -9,6 +9,7 @@ using Avalonia.Input.Platform;
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Controls;
using Avalonia.Threading;
namespace Avalonia
{
@ -91,14 +92,14 @@ namespace Avalonia.Gtk
public void Signal()
public void Signal(DispatcherPriority prio)
{
Gtk.Application.Invoke(delegate { Signaled?.Invoke(); });
Gtk.Application.Invoke(delegate { Signaled?.Invoke(null); });
}
public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _uiThread;
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
public IWindowImpl CreateWindow()
{
return new WindowImpl();

Просмотреть файл

@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
@ -28,33 +27,6 @@
<Compile Include="..\Avalonia.Gtk\KeyTransform.cs">
<Link>KeyTransform.cs</Link>
</Compile>
<Compile Include="Interop\CairoSurface.cs" />
<Compile Include="ClipboardImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="FramebufferManager.cs" />
<Compile Include="GdkCursor.cs" />
<Compile Include="GdkKey.cs" />
<Compile Include="Gtk3Platform.cs" />
<Compile Include="Interop\GException.cs" />
<Compile Include="Interop\GObject.cs" />
<Compile Include="Interop\ICustomGtk3NativeLibraryResolver.cs" />
<Compile Include="Interop\DynLoader.cs" />
<Compile Include="Interop\GlibTimeout.cs" />
<Compile Include="Interop\Native.cs" />
<Compile Include="Interop\NativeException.cs" />
<Compile Include="Interop\Pixbuf.cs" />
<Compile Include="Interop\Resolver.cs" />
<Compile Include="Interop\Signal.cs" />
<Compile Include="ImageSurfaceFramebuffer.cs" />
<Compile Include="PlatformIconLoader.cs" />
<Compile Include="PopupImpl.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SystemDialogs.cs" />
<Compile Include="WindowBaseImpl.cs" />
<Compile Include="Interop\Utf8Buffer.cs" />
<Compile Include="WindowImpl.cs" />
<Compile Include="ScreenImpl.cs" />
<Compile Include="GtkScreen.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />

Просмотреть файл

@ -12,6 +12,7 @@ using Avalonia.Input.Platform;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Gtk3;
using Avalonia.Threading;
namespace Avalonia.Gtk3
{
@ -68,27 +69,28 @@ namespace Avalonia.Gtk3
return GlibTimeout.StarTimer((uint) interval.TotalMilliseconds, tick);
}
private bool _signaled = false;
private bool[] _signaled = new bool[(int) DispatcherPriority.MaxValue + 1];
object _lock = new object();
public void Signal()
public void Signal(DispatcherPriority prio)
{
var idx = (int) prio;
lock(_lock)
if (!_signaled)
if (!_signaled[idx])
{
_signaled = true;
GlibTimeout.Add(0, () =>
_signaled[idx] = true;
GlibTimeout.Add(GlibPriority.FromDispatcherPriority(prio), 0, () =>
{
lock (_lock)
{
_signaled = false;
_signaled[idx] = false;
}
Signaled?.Invoke();
Signaled?.Invoke(prio);
return false;
});
}
}
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
[ThreadStatic]

Просмотреть файл

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Threading;
namespace Avalonia.Gtk3.Interop
{
static class GlibPriority
{
public static int High = -100;
public static int Default = 0;
public static int HighIdle = 100;
public static int GtkResize = HighIdle + 10;
public static int GtkPaint = HighIdle + 20;
public static int DefaultIdle = 200;
public static int Low = 300;
public static int GdkEvents = Default;
public static int GdkRedraw = HighIdle + 20;
public static int FromDispatcherPriority(DispatcherPriority prio)
{
if (prio == DispatcherPriority.Send)
return High;
if (prio == DispatcherPriority.Normal)
return Default - 4;
if (prio == DispatcherPriority.DataBind)
return Default - 3;
if (prio == DispatcherPriority.Render)
return Default -2;
if (prio == DispatcherPriority.Loaded)
return Default - 1;
if (prio == DispatcherPriority.Input)
return Default;
if (prio == DispatcherPriority.Background)
return DefaultIdle;
if (prio == DispatcherPriority.ContextIdle)
return DefaultIdle + 100;
if (prio == DispatcherPriority.ApplicationIdle)
return DefaultIdle + 200;
if (prio == DispatcherPriority.SystemIdle)
return DefaultIdle + 200;
throw new ArgumentException("Unknown priority");
}
}
}

Просмотреть файл

@ -30,7 +30,7 @@ namespace Avalonia.Gtk3.Interop
}
public static void Add(uint interval, Func<bool> callback)
public static void Add(int priority, uint interval, Func<bool> callback)
{
var handle = GCHandle.Alloc(callback);
Native.GTimeoutAdd(interval, PinnedHandler, GCHandle.ToIntPtr(handle));
@ -49,7 +49,7 @@ namespace Avalonia.Gtk3.Interop
public static IDisposable StarTimer(uint interval, Action tick)
{
var timer = new Timer ();
GlibTimeout.Add(interval,
GlibTimeout.Add(101, interval,
() =>
{
if (timer.Stopped)

Просмотреть файл

@ -236,6 +236,9 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_process_updates(IntPtr window, bool updateChildren);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_event_request_motions(IntPtr ev);
@ -287,7 +290,10 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public delegate ulong g_timeout_add(uint interval, timeout_callback callback, IntPtr data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public delegate ulong g_timeout_add_full(int prio, uint interval, timeout_callback callback, IntPtr data, IntPtr destroy);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public delegate ulong g_free(IntPtr data);
@ -366,6 +372,7 @@ namespace Avalonia.Gtk3.Interop
public static D.g_signal_connect_object GSignalConnectObject;
public static D.g_signal_handler_disconnect GSignalHandlerDisconnect;
public static D.g_timeout_add GTimeoutAdd;
public static D.g_timeout_add_full GTimeoutAddFull;
public static D.g_free GFree;
public static D.g_slist_free GSlistFree;
public static D.g_memory_input_stream_new_from_data GMemoryInputStreamNewFromData;
@ -398,6 +405,7 @@ namespace Avalonia.Gtk3.Interop
public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag;
public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag;
public static D.gdk_event_request_motions GdkEventRequestMotions;
public static D.gdk_window_process_updates GdkWindowProcessUpdates;
public static D.gdk_pixbuf_new_from_file GdkPixbufNewFromFile;
public static D.gtk_icon_theme_get_default GtkIconThemeGetDefault;

Просмотреть файл

@ -140,13 +140,11 @@ namespace Avalonia.Gtk3.Interop
var nativeHandleNames = new[] { "gdk_win32_window_get_handle", "gdk_x11_window_get_xid", "gdk_quartz_window_get_nswindow" };
foreach (var name in nativeHandleNames)
{
try
{
Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle)Marshal
.GetDelegateForFunctionPointer(loader.GetProcAddress(dlls[GtkDll.Gdk], name, false), typeof(Native.D.gdk_get_native_handle));
break;
}
catch { }
var ptr = loader.GetProcAddress(dlls[GtkDll.Gdk], name, true);
if (ptr == IntPtr.Zero)
continue;
Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle) Marshal
.GetDelegateForFunctionPointer(ptr, typeof(Native.D.gdk_get_native_handle));
}
if (Native.GetNativeGdkWindowHandle == null)
throw new Exception($"Unable to locate any of [{string.Join(", ", nativeHandleNames)}] in libgdk");

Просмотреть файл

@ -10,6 +10,7 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
namespace Avalonia.Gtk3
{
@ -25,6 +26,7 @@ namespace Avalonia.Gtk3
private double _lastScaling;
private uint _lastKbdEvent;
private uint _lastSmoothScrollEvent;
private bool _hasDirtyRects;
public WindowBaseImpl(GtkWindow gtkWidget)
{
@ -222,6 +224,7 @@ namespace Avalonia.Gtk3
private bool OnDraw(IntPtr gtkwidget, IntPtr cairocontext, IntPtr userdata)
{
_hasDirtyRects = false;
CurrentCairoContext = cairocontext;
Paint?.Invoke(new Rect(ClientSize));
CurrentCairoContext = IntPtr.Zero;
@ -271,6 +274,19 @@ namespace Avalonia.Gtk3
if(GtkWidget.IsClosed)
return;
Native.GtkWidgetQueueDrawArea(GtkWidget, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
if (!_hasDirtyRects)
{
_hasDirtyRects = true;
Dispatcher.UIThread.InvokeAsync(() =>
{
if (GtkWidget.IsClosed)
return;
var window = Native.GtkWidgetGetWindow(GtkWidget);
if (window == IntPtr.Zero)
return;
Native.GdkWindowProcessUpdates(window, false);
}, DispatcherPriority.Render);
}
}
public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;

Просмотреть файл

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
namespace Avalonia.LinuxFramebuffer
{
@ -30,7 +31,7 @@ namespace Avalonia.LinuxFramebuffer
while (true)
{
if (0 == WaitHandle.WaitAny(handles))
Signaled?.Invoke();
Signaled?.Invoke(null);
else
{
while (true)
@ -97,7 +98,7 @@ namespace Avalonia.LinuxFramebuffer
}
public void Signal()
public void Signal(DispatcherPriority prio)
{
_signaled.Set();
}
@ -105,7 +106,7 @@ namespace Avalonia.LinuxFramebuffer
[ThreadStatic] private static bool TlsCurrentThreadIsLoopThread;
public bool CurrentThreadIsLoopThread => TlsCurrentThreadIsLoopThread;
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
public event EventHandler<EventArgs> Tick;
}

Просмотреть файл

@ -1,6 +1,7 @@
using System;
using System.Threading;
using Avalonia.Platform;
using Avalonia.Threading;
using MonoMac.AppKit;
using MonoMac.CoreGraphics;
using MonoMac.Foundation;
@ -13,12 +14,12 @@ namespace Avalonia.MonoMac
public static PlatformThreadingInterface Instance { get; } = new PlatformThreadingInterface();
public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread;
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
public IDisposable StartTimer(TimeSpan interval, Action tick)
=> NSTimer.CreateRepeatingScheduledTimer(interval, () => tick());
public void Signal()
public void Signal(DispatcherPriority prio)
{
lock (this)
{
@ -34,7 +35,7 @@ namespace Avalonia.MonoMac
return;
_signaled = false;
}
Signaled?.Invoke();
Signaled?.Invoke(null);
});
}

Просмотреть файл

@ -15,6 +15,7 @@ using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using Avalonia.Controls;
using Avalonia.Rendering;
using Avalonia.Threading;
#if NETSTANDARD
using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception;
#else
@ -137,7 +138,7 @@ namespace Avalonia.Win32
private static readonly int SignalW = unchecked((int) 0xdeadbeaf);
private static readonly int SignalL = unchecked((int)0x12345678);
public void Signal()
public void Signal(DispatcherPriority prio)
{
UnmanagedMethods.PostMessage(
_hwnd,
@ -148,14 +149,14 @@ namespace Avalonia.Win32
public bool CurrentThreadIsLoopThread => _uiThread == UnmanagedMethods.GetCurrentThreadId();
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg == (int) UnmanagedMethods.WindowsMessage.WM_DISPATCH_WORK_ITEM && wParam.ToInt64() == SignalW && lParam.ToInt64() == SignalL)
{
Signaled?.Invoke();
Signaled?.Invoke(null);
}
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
}

Просмотреть файл

@ -16,6 +16,7 @@ using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using static Avalonia.Win32.Interop.UnmanagedMethods;
using Avalonia.Rendering;
using Avalonia.Threading;
#if NETSTANDARD
using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception;
#endif

Просмотреть файл

@ -9,6 +9,7 @@ using CoreAnimation;
using Foundation;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.Threading;
namespace Avalonia.iOS
{
@ -18,7 +19,7 @@ namespace Avalonia.iOS
public static PlatformThreadingInterface Instance { get; } = new PlatformThreadingInterface();
public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread;
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
public void RunLoop(CancellationToken cancellationToken)
{
//Mobile platforms are using external main loop
@ -53,7 +54,7 @@ namespace Avalonia.iOS
public IDisposable StartTimer(TimeSpan interval, Action tick)
=> NSTimer.CreateRepeatingScheduledTimer(interval, _ => tick());
public void Signal()
public void Signal(DispatcherPriority prio)
{
lock (this)
{
@ -65,7 +66,7 @@ namespace Avalonia.iOS
{
lock (this)
_signaled = false;
Signaled?.Invoke();
Signaled?.Invoke(null);
});
}
}

Просмотреть файл

@ -6,6 +6,7 @@ using System.Reactive.Subjects;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Platform;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Xunit;
@ -147,14 +148,14 @@ namespace Avalonia.Base.UnitTests
public bool CurrentThreadIsLoopThread { get; set; }
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
public void RunLoop(CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public void Signal()
public void Signal(DispatcherPriority prio)
{
throw new NotImplementedException();
}

Просмотреть файл

@ -13,7 +13,7 @@ using Avalonia.Platform;
using System.Threading.Tasks;
using System;
using System.Threading;
using Avalonia.Threading;
#if AVALONIA_CAIRO
using Avalonia.Cairo;
#elif AVALONIA_SKIA
@ -155,14 +155,14 @@ namespace Avalonia.Direct2D1.RenderTests
public Thread MainThread { get; set; }
public event Action Signaled;
public event Action<DispatcherPriority?> Signaled;
public void RunLoop(CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public void Signal()
public void Signal(DispatcherPriority prio)
{
throw new NotImplementedException();
}