Browse Source
* Refactored DispatcherPriorityAwaitable, implemented Dispatcher.Yield * Picked changes from https://github.com/AvaloniaUI/Avalonia/pull/14212 * Format/compile * Update API suppressions --------- Co-authored-by: Yoh Deadfall <yoh.deadfall@hotmail.com> Co-authored-by: Julien Lebosquain <julien@lebosquain.net>pull/19387/head
committed by
GitHub
4 changed files with 332 additions and 16 deletions
@ -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(); |
|||
} |
|||
Loading…
Reference in new issue