From 90a0f89010965d12ed2c897304737aa2cac934d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20B=C3=B6rchers?= Date: Mon, 4 May 2020 22:05:14 +0200 Subject: [PATCH] Playing with Prisms TaskExtension --- App/MainWindowViewModel.cs | 3 +- App/MvvmStuff/BaseViewModel.cs | 2 +- App/MvvmStuff/TaskExtensions.cs | 85 +++++++++++++++++ App/MvvmStuff/TaskExtensions{T}.cs | 91 +++++++++++++++++++ .../PropertyPresenter/PropertyPresenter.xaml | 2 +- 5 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 App/MvvmStuff/TaskExtensions.cs create mode 100644 App/MvvmStuff/TaskExtensions{T}.cs diff --git a/App/MainWindowViewModel.cs b/App/MainWindowViewModel.cs index df37387..6614b88 100644 --- a/App/MainWindowViewModel.cs +++ b/App/MainWindowViewModel.cs @@ -11,6 +11,7 @@ using YamlDotNet.Serialization; namespace ModernWpfPlayground { + // ReSharper disable once ClassNeverInstantiated.Global public class MainWindowViewModel : BaseViewModel { private const string AppName = "TaBEA 3.0.0"; @@ -21,7 +22,7 @@ namespace ModernWpfPlayground public MainWindowViewModel() { - ShowDialogCommand = new DelegateCommand(async () => await ShowDialogAsync().ConfigureAwait(false)); + ShowDialogCommand = new DelegateCommand(() => ShowDialogAsync().Await()); CloseCommand = new DelegateCommand(() => Application.Current.Shutdown()); OpenViewModelCommand = new DelegateCommand(LoadViewModel); SaveViewModelCommand = new DelegateCommand(SaveViewModel); diff --git a/App/MvvmStuff/BaseViewModel.cs b/App/MvvmStuff/BaseViewModel.cs index 33d927b..3da39e4 100644 --- a/App/MvvmStuff/BaseViewModel.cs +++ b/App/MvvmStuff/BaseViewModel.cs @@ -39,7 +39,7 @@ namespace ModernWpfPlayground.MvvmStuff protected void ResetViewModel(Func? predicate = null) { - IEnumerable keys = _values.Keys; + IEnumerable keys = _values.Keys.ToArray(); if (predicate != null) keys = keys.Where(predicate); foreach (var key in keys) { diff --git a/App/MvvmStuff/TaskExtensions.cs b/App/MvvmStuff/TaskExtensions.cs new file mode 100644 index 0000000..e315c7d --- /dev/null +++ b/App/MvvmStuff/TaskExtensions.cs @@ -0,0 +1,85 @@ +// ReSharper disable CheckNamespace +namespace System.Threading.Tasks +{ + /// + /// Extension methods for the Task object. + /// + public static class TaskExtensions + { + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The task to be awaited + public static void Await(this Task task) + { + task.Await(null, null, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The task to be awaited + /// Configures an awaiter used to await this task + public static void Await(this Task task, bool configureAwait) + { + task.Await(null, null, configureAwait); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The task to be awaited + /// The action to perform when the task is complete. + public static void Await(this Task task, Action completedCallback) + { + task.Await(completedCallback, null, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The task to be awaited + /// The action to perform when the task is complete. + /// The action to perform when an error occurs executing the task. + public static void Await(this Task task, Action completedCallback, Action errorCallback) + { + task.Await(completedCallback, errorCallback, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The task to be awaited + /// The action to perform when an error occurs executing the task. + public static void Await(this Task task, Action errorCallback) + { + task.Await(null, errorCallback, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The task to be awaited + /// The action to perform when the task is complete. + /// The action to perform when an error occurs executing the task. + /// Configures an awaiter used to await this task + public async static void Await(this Task task, Action? completedCallback, Action? errorCallback, bool configureAwait) + { + try + { + await task.ConfigureAwait(configureAwait); + completedCallback?.Invoke(); + } + catch (Exception ex) + { + errorCallback?.Invoke(ex); + } + } + } +} diff --git a/App/MvvmStuff/TaskExtensions{T}.cs b/App/MvvmStuff/TaskExtensions{T}.cs new file mode 100644 index 0000000..5d3364f --- /dev/null +++ b/App/MvvmStuff/TaskExtensions{T}.cs @@ -0,0 +1,91 @@ +// ReSharper disable CheckNamespace +namespace System.Threading.Tasks +{ + /// + /// Extension methods for the Task object. + /// + public static class TaskExtensionsT + { + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The result type + /// The task to be awaited + public static void Await(this Task task) + { + task.Await(null, null, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The result type + /// The task to be awaited + /// Configures an awaiter used to await this task + public static void Await(this Task task, bool configureAwait) + { + task.Await(null, null, configureAwait); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The result type + /// The task to be awaited + /// The action to perform when the task is complete. + public static void Await(this Task task, Action completedCallback) + { + task.Await(completedCallback, null, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The result type + /// The task to be awaited + /// The action to perform when the task is complete. + /// The action to perform when an error occurs executing the task. + public static void Await(this Task task, Action completedCallback, Action errorCallback) + { + task.Await(completedCallback, errorCallback, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The result type + /// The task to be awaited + /// The action to perform when an error occurs executing the task. + public static void Await(this Task task, Action errorCallback) + { + task.Await(null, errorCallback, false); + } + + /// + /// Awaits a task without blocking the main thread. + /// + /// Primarily used to replace async void scenarios such as ctor's and ICommands. + /// The result type + /// The task to be awaited + /// The action to perform when the task is complete. + /// The action to perform when an error occurs executing the task. + /// Configures an awaiter used to await this task + public async static void Await(this Task task, Action? completedCallback, Action? errorCallback, bool configureAwait) + { + try + { + var result = await task.ConfigureAwait(configureAwait); + completedCallback?.Invoke(result); + } + catch (Exception ex) + { + errorCallback?.Invoke(ex); + } + } + } +} diff --git a/Controls/PropertyPresenter/PropertyPresenter.xaml b/Controls/PropertyPresenter/PropertyPresenter.xaml index 3d88785..03f6276 100644 --- a/Controls/PropertyPresenter/PropertyPresenter.xaml +++ b/Controls/PropertyPresenter/PropertyPresenter.xaml @@ -2,9 +2,9 @@ x:Class="Controls.PropertyPresenter" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:controls="clr-namespace:Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:controls="clr-namespace:Controls" x:Name="LayoutRoot" d:DesignHeight="300" d:DesignWidth="300"