From 92327dcc0d348c2edee38acfb35143d18153e9e1 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Thu, 28 Jul 2022 10:40:39 -0600 Subject: [PATCH] Add synchronous thread extensions --- .../LibationAvalonia/AvaloniaThreadUtils.cs | 46 +++++++++++++++++++ Source/LibationAvalonia/AvaloniaUtils.cs | 7 +-- Source/LibationAvalonia/MessageBox.cs | 8 ++-- 3 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 Source/LibationAvalonia/AvaloniaThreadUtils.cs diff --git a/Source/LibationAvalonia/AvaloniaThreadUtils.cs b/Source/LibationAvalonia/AvaloniaThreadUtils.cs new file mode 100644 index 00000000..b14f6ec0 --- /dev/null +++ b/Source/LibationAvalonia/AvaloniaThreadUtils.cs @@ -0,0 +1,46 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Avalonia.Threading +{ + internal static class AvaloniaThreadUtils + { + public static TResult Invoke(this Dispatcher dispatcher, Func function, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal) + { + using var source = new CancellationTokenSource(); + var task = dispatcher.InvokeAsync(function, dispatcherPriority); + task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext()); + dispatcher.MainLoop(source.Token); + return task.Result; + } + + public static void Invoke(this Dispatcher dispatcher, Action action, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal) + { + using var source = new CancellationTokenSource(); + var task = dispatcher.InvokeAsync(action, dispatcherPriority); + task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext()); + Dispatcher.UIThread.MainLoop(source.Token); + } + + public static T WaitOnUIAndGetResult(this Task task) + => WaitOnDispatcherAndGetResult(task, Dispatcher.UIThread); + + public static T WaitOnDispatcherAndGetResult(this Task task, Dispatcher dispatcher) + { + using var source = new CancellationTokenSource(); + task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext()); + dispatcher.MainLoop(source.Token); + return task.Result; + } + + public static void WaitOnUI(this Task task) + => WaitOnDispatcher(task, Dispatcher.UIThread); + public static void WaitOnDispatcher(this Task task, Dispatcher dispatcher) + { + using var source = new CancellationTokenSource(); + task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext()); + dispatcher.MainLoop(source.Token); + } + } +} diff --git a/Source/LibationAvalonia/AvaloniaUtils.cs b/Source/LibationAvalonia/AvaloniaUtils.cs index 7ade8b9a..6efc93a5 100644 --- a/Source/LibationAvalonia/AvaloniaUtils.cs +++ b/Source/LibationAvalonia/AvaloniaUtils.cs @@ -1,4 +1,5 @@ using Avalonia.Media; +using Avalonia.Threading; using System; using System.Threading; using System.Threading.Tasks; @@ -18,11 +19,7 @@ namespace LibationAvalonia public static T ShowDialogSynchronously(this Avalonia.Controls.Window window, Avalonia.Controls.Window owner) { - using var source = new CancellationTokenSource(); - var dialogTask = window.ShowDialog(owner); - dialogTask.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext()); - Avalonia.Threading.Dispatcher.UIThread.MainLoop(source.Token); - return dialogTask.Result; + return window.ShowDialog(owner).WaitOnUIAndGetResult(); } } } diff --git a/Source/LibationAvalonia/MessageBox.cs b/Source/LibationAvalonia/MessageBox.cs index 39d4ac66..3ad00a8f 100644 --- a/Source/LibationAvalonia/MessageBox.cs +++ b/Source/LibationAvalonia/MessageBox.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Threading; +using Avalonia.Threading; namespace LibationAvalonia { @@ -150,12 +151,9 @@ Libation. private static DialogResult ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true) { - using var source = new CancellationTokenSource(); - var dialogTask = Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition)); - dialogTask.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext()); - Avalonia.Threading.Dispatcher.UIThread.MainLoop(source.Token); + var dialogTask = Dispatcher.UIThread.Invoke(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition)); - return DisplayWindow(dialogTask.Result, owner); + return DisplayWindow(dialogTask, owner); } private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)