Add ICommand implementation that support async execution and allow the prevention of simultaneous/reentrant execution.
Maybe take MVVM Helpers implementation of AsyncCommand.
Based on IAsyncCommand defined on MVVM Helpers:
````cs
///
/// Interface for Async Command
///
public interface IAsyncCommand : ICommand
{
///
/// Allow simultaneous/reentrant execution.
/// Default value is True.
///
bool AllowMultipleExecution { get; set; }
/// <summary>
/// Execute the command async.
/// </summary>
/// <returns>Task to be awaited on.</returns>
Task ExecuteAsync();
/// <summary>
/// Raise a CanExecute change event.
/// </summary>
void RaiseCanExecuteChanged();
}
///
/// Interface for Async Command with parameter
///
public interface IAsyncCommand
{
///
/// Allow simultaneous/reentrant execution.
/// Default value is True.
///
bool AllowMultipleExecution { get; set; }
/// <summary>
/// Execute the command async.
/// </summary>
/// <param name="parameter">Parameter to pass to command</param>
/// <returns>Task to be awaited on.</returns>
Task ExecuteAsync(T parameter);
/// <summary>
/// Raise a CanExecute change event.
/// </summary>
void RaiseCanExecuteChanged();
}
````
Nice idea!)
Nice idea!)
Lovely! Since we already have the blessing of James, do you want to port that over yourself @YZahringer or you want us to do it?
@jfversluis I can port this. I have some doubts:
Xamarin.CommunityToolkit.Commands?Xamarin.CommunityToolkit.Input?Xamarin.CommunityToolkit.Core?Xamarin.CommunityToolkit.ObjectModel?AllowMultipleExecution?What would you like to adapt? In the issue I see linked there is also the implementation from @brminnick which seems already improved? I'm almost certain he would allow us to take that if it has changes you'd like to see. We could also try to force an answer for that Forms issue by just opening a PR to make that class public and see what they say. I can do that if needed
Good question. At this point I would like to try and not expand to any more namespaces. ObjectModel I guess?
Again; what would you like to change?
Hi friends!
Feel free to assign this to me.
I鈥檇 be happy to port my implementation of AsyncCommand from AsyncAwaitBestPractices
@brminnick Sounds good. What's the actual difference between these implementations? And if there are differences, could we come to a best of both worlds covering e.g. concerns as mentioned above by @YZahringer?
Yup - it's no problem to merge everything!
MVVMHelpers' AsyncCommand implementation was actually inspired by AsyncAwaitBestPractices:
To answer your question, AsyncAwaitBestPractices has some performance improvements, includes support for ValueTask and has a robust suite of unit tests; all of which I'll be porting into XamarinCommunityToolkit!
Looking at the spec, above, I'll be making two small changes:
ValueTaskIAsyncCommand.AllowMultipleExecutionsValueTask was introduced in .NET Standard 2.1 and offers performance gains over Task.
AllowMultipleExecutions isn't necessary for ICommand and it breaks the ICommand stateless paradigm. ICommand includes CanExecute which is what should be used to prevent multiple executions. ICommand should be stateless and AllowMultipleExecutions implements a state-pattern by tracking whether or not the Task is currently running.
@brminnick I agree, AllowMultipleExecutions is not stateless in ICommand. But it is very useful and simple solution for a recurrent problem to maintain every time you use IAsyncCommand.
Without this, you have to manage in every VM an IsBusy, set on try...finally in each execute, canExecute => !IsBusy and raise can execute changed when IsBusy changed.
For example, ReactiveUI Commands use the same approach for async commands with IsExecuting property and block re-execution while executing. DevExpress.Mvvm Commands also define AllowMultipleExecution and IsExecuting.
Interesting - I didn't realize there was a paradigm shift, adding this to other AsyncCommands!
I'll pause and delve into these implementations to understand the ecosystem a bit better 馃憤
Most helpful comment
Interesting - I didn't realize there was a paradigm shift, adding this to other
AsyncCommands!I'll pause and delve into these implementations to understand the ecosystem a bit better 馃憤