|
|
@@ -1,40 +1,130 @@
|
|
|
using System;
|
|
|
using System.Runtime.CompilerServices;
|
|
|
+using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
namespace Avalonia.Threading;
|
|
|
|
|
|
-public class DispatcherPriorityAwaitable : INotifyCompletion
|
|
|
+/// <summary>
|
|
|
+/// A simple awaitable type that will return a DispatcherPriorityAwaiter.
|
|
|
+/// </summary>
|
|
|
+public struct DispatcherPriorityAwaitable
|
|
|
{
|
|
|
private readonly Dispatcher _dispatcher;
|
|
|
- private protected readonly Task Task;
|
|
|
+ private readonly Task? _task;
|
|
|
private readonly DispatcherPriority _priority;
|
|
|
|
|
|
- internal DispatcherPriorityAwaitable(Dispatcher dispatcher, Task task, DispatcherPriority priority)
|
|
|
+ internal DispatcherPriorityAwaitable(Dispatcher dispatcher, Task? task, DispatcherPriority priority)
|
|
|
{
|
|
|
_dispatcher = dispatcher;
|
|
|
- Task = task;
|
|
|
+ _task = task;
|
|
|
_priority = priority;
|
|
|
}
|
|
|
-
|
|
|
- public void OnCompleted(Action continuation) =>
|
|
|
- Task.ContinueWith(_ => _dispatcher.Post(continuation, _priority));
|
|
|
|
|
|
- public bool IsCompleted => Task.IsCompleted;
|
|
|
+ public DispatcherPriorityAwaiter GetAwaiter() => new(_dispatcher, _task, _priority);
|
|
|
+}
|
|
|
+
|
|
|
+/// <summary>
|
|
|
+/// A simple awaiter type that will queue the continuation to a dispatcher at a specific priority.
|
|
|
+/// </summary>
|
|
|
+/// <remarks>
|
|
|
+/// This is returned from DispatcherPriorityAwaitable.GetAwaiter()
|
|
|
+/// </remarks>
|
|
|
+public struct DispatcherPriorityAwaiter : INotifyCompletion
|
|
|
+{
|
|
|
+ private readonly Dispatcher _dispatcher;
|
|
|
+ private readonly Task? _task;
|
|
|
+ private readonly DispatcherPriority _priority;
|
|
|
+
|
|
|
+ internal DispatcherPriorityAwaiter(Dispatcher dispatcher, Task? task, DispatcherPriority priority)
|
|
|
+ {
|
|
|
+ _dispatcher = dispatcher;
|
|
|
+ _task = task;
|
|
|
+ _priority = priority;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnCompleted(Action continuation)
|
|
|
+ {
|
|
|
+ if(_task == null || _task.IsCompleted)
|
|
|
+ _dispatcher.Post(continuation, _priority);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var self = this;
|
|
|
+ _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() =>
|
|
|
+ {
|
|
|
+ self._dispatcher.Post(continuation, self._priority);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// This always returns false since continuation is requested to be queued to a dispatcher queue
|
|
|
+ /// </summary>
|
|
|
+ public bool IsCompleted => false;
|
|
|
+
|
|
|
+ public void GetResult()
|
|
|
+ {
|
|
|
+ if (_task != null)
|
|
|
+ _task.GetAwaiter().GetResult();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/// <summary>
|
|
|
+/// A simple awaitable type that will return a DispatcherPriorityAwaiter<T>.
|
|
|
+/// </summary>
|
|
|
+public struct DispatcherPriorityAwaitable<T>
|
|
|
+{
|
|
|
+ private readonly Dispatcher _dispatcher;
|
|
|
+ private readonly Task<T> _task;
|
|
|
+ private readonly DispatcherPriority _priority;
|
|
|
|
|
|
- public void GetResult() => Task.GetAwaiter().GetResult();
|
|
|
+ internal DispatcherPriorityAwaitable(Dispatcher dispatcher, Task<T> task, DispatcherPriority priority)
|
|
|
+ {
|
|
|
+ _dispatcher = dispatcher;
|
|
|
+ _task = task;
|
|
|
+ _priority = priority;
|
|
|
+ }
|
|
|
|
|
|
- public DispatcherPriorityAwaitable GetAwaiter() => this;
|
|
|
+ public DispatcherPriorityAwaiter<T> GetAwaiter() => new(_dispatcher, _task, _priority);
|
|
|
}
|
|
|
|
|
|
-public sealed class DispatcherPriorityAwaitable<T> : DispatcherPriorityAwaitable
|
|
|
+/// <summary>
|
|
|
+/// A simple awaiter type that will queue the continuation to a dispatcher at a specific priority.
|
|
|
+/// </summary>
|
|
|
+/// <remarks>
|
|
|
+/// This is returned from DispatcherPriorityAwaitable<T>.GetAwaiter()
|
|
|
+/// </remarks>
|
|
|
+public struct DispatcherPriorityAwaiter<T> : INotifyCompletion
|
|
|
{
|
|
|
- internal DispatcherPriorityAwaitable(Dispatcher dispatcher, Task<T> task, DispatcherPriority priority) : base(
|
|
|
- dispatcher, task, priority)
|
|
|
+ private readonly Dispatcher _dispatcher;
|
|
|
+ private readonly Task<T> _task;
|
|
|
+ private readonly DispatcherPriority _priority;
|
|
|
+
|
|
|
+ internal DispatcherPriorityAwaiter(Dispatcher dispatcher, Task<T> task, DispatcherPriority priority)
|
|
|
{
|
|
|
+ _dispatcher = dispatcher;
|
|
|
+ _task = task;
|
|
|
+ _priority = priority;
|
|
|
}
|
|
|
|
|
|
- public new T GetResult() => ((Task<T>)Task).GetAwaiter().GetResult();
|
|
|
+ public void OnCompleted(Action continuation)
|
|
|
+ {
|
|
|
+ if(_task.IsCompleted)
|
|
|
+ _dispatcher.Post(continuation, _priority);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var self = this;
|
|
|
+ _task.ConfigureAwait(false).GetAwaiter().OnCompleted(() =>
|
|
|
+ {
|
|
|
+ self._dispatcher.Post(continuation, self._priority);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// This always returns false since continuation is requested to be queued to a dispatcher queue
|
|
|
+ /// </summary>
|
|
|
+ public bool IsCompleted => false;
|
|
|
|
|
|
- public new DispatcherPriorityAwaitable<T> GetAwaiter() => this;
|
|
|
-}
|
|
|
+ public void GetResult() => _task.GetAwaiter().GetResult();
|
|
|
+}
|