AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.22k stars 2.18k forks source link

Add Yield method to Dispatcher for async programming #14199

Open YohDeadfall opened 8 months ago

YohDeadfall commented 8 months ago

Design

The proposal is about adding adding two methods to be used while writing async code for easy thread or priority switching when it's required:

public class Dispatcher
{
+    public static DispatcherPriorityAwaiter Yield() =>
+         new DispatcherPriority.Background);

+    public static DispatcherPriorityAwaiter Yield(DispatcherPriority priority)
+         new(priority);
}

Methods are made static since while the Dispatcher type isn't static, there's only one instance of it without exceptions.

public readonly struct DispatcherPriorityAwaiter : INotifyCompletion
{
    private readonly DispatcherPriority _priority;

    public DispatcherPriorityAwaiter(DispatcherPriority priority) => _priority = priority;

    public void GetResult() { }

    public bool IsCompleted => false;
    public void OnCompleted(Action continuation) => Dispatcher.UIThread.Post(continuation, _priority);
}

DispatcherPriorityAwaiter is a struct, so it can be inlined into a state machine generated by the compiler for the method where the awaiter is used.

Usage

async Task DoSomethingAsync()
{
    // Do something in background
    // ...

    // Here we go to UI
    await Dispatcher.Yield();

    // Now it's possible to interact with UI components
}

The same thing is already provided by WPF via the same named methods. So for newcomers it should take less code to change during migration.

Alternatives

An alternative solution is to use AwaitWithPriority, but it requires a task to be passed in which means more allocations and more code to be written.

maxkatz6 commented 8 months ago

Methods are made static since while the Dispatcher type isn't static, there's only one instance of it without exceptions.

That’s not true, we have exceptions - XPF ;) And in general, we still want to keep a possibility to allow multiple dispatcher threads, at least for testing.

YohDeadfall commented 8 months ago

Then should it be also more WPF compatible, so parameterless Yiled will use DispatcherPriority.Background?