How to use async method in DelegateCommand

I want to associate the async method with the delegate command in the prism structure in Xamarin.Forms, and my question is: how to do this?

Is the decision right? Is there any mistake? (dead end, slow or frozen user interface, bad practice, ...)

{      // My view model constructor
       ... 
       MyCommand = new DelegateCommand(async () => await MyJobAsync());
       ...
}

private async Task MyJobAsync()
{
       ... // Some await calls
       ... // Some UI element changed such as binded Observable collections
}
+6
source share
7 answers

You can use directly async void. However, a few comments from my experience ...

: , . , NotifyTask<T> , . . async MVVM NotifyTask<T> ( , ).

( ), async void async, MVVM. , API .

async void :

  • , async Task , , .
  • . DelegateTask, .
+5

, - async void. , . , ICommand, Xamarin Command, Prism DelegateCommand ICommand void Execute(object obj). , , , DelegateCommand.FromAsync .

, . . Exceptions "", FromAsync , , . async void , , , , . DelegateCommands ObservesProperty ObservesCanExecute.

+2

, , ?

, DelegateCommand. async , await, . awaiter (.. .ConfigureAwait(false)), DelegateCommand await.

, , ?

"" , , , api. , cpu-bound threadpool Task.Run - - Stream.ReadAsync

+1

, (ICommand.Execute): 1) 2) . , (). DelegateCommand.

public sealed class AsyncDelegateCommand : ICommand
{
    private readonly Func<object, Task> func;
    private readonly Action<Exception> faultHandlerAction;
    private int callRunning = 0;

    // Pass in the async delegate (which takes an object parameter and returns a Task) 
    // and a delegate which handles exceptions
    public AsyncDelegateCommand(Func<object, Task> func, Action<Exception> faultHandlerAction)
    {
        this.func = func;
        this.faultHandlerAction = faultHandlerAction;
    }

    public bool CanExecute(object parameter)
    {
        return callRunning == 0;
    }

    public void Execute(object parameter)
    {
        // Replace value of callRunning with 1 if 0, otherwise return - (if already 1).
        // This ensures that there is only one running call at a time.
        if (Interlocked.CompareExchange(ref callRunning, 1, 0) == 1)
        {
            return;
        }
        OnCanExecuteChanged();
        func(parameter).ContinueWith((task, _) => ExecuteFinished(task), null, TaskContinuationOptions.ExecuteSynchronously);
    }

    private void ExecuteFinished(Task task)
    {
        // Replace value of callRunning with 0
        Interlocked.Exchange(ref callRunning, 0);
        // Call error handling if task has faulted
        if (task.IsFaulted)
        {
            faultHandlerAction(task.Exception);
        }
        OnCanExecuteChanged();
    }

    public event EventHandler CanExecuteChanged;

    private void OnCanExecuteChanged()
    {
        // Raising this event tells for example a button to display itself as "grayed out" while async operation is still running
        var handler = CanExecuteChanged;
        if (handler != null) handler(this, EventArgs.Empty);
    }
}

async void

" " . , , . , , "async Task", "async void", , :

public async Task SomeLogic()
{
    var success = await SomeFurtherLogic();
    if (!success) 
    {
        throw new DomainException(..); // Normal thing to do
    }
}

- :

public async void CommandHandler()
{
    await SomeLogic();  // Calling a method. Normal thing to do but can lead to an unobserved Task exception
}
+1
public ICommand MyCommand{get;set;}

//constructor
public ctor()
{
    MyCommand = new Xamarin.Forms.Command(CmdDoTheJob);
}

public async void DoTheJob()
{
    await TheMethod();
}
0
public DelegateCommand MyCommand => new DelegateCommand(MyMethod);

private async void MyMethod()
{

}

. void async-. - , , :

Device.BeginOnMainThread(()=>
{
    your code;
});

, ICommand DelegateCommand , .

0

Change your code in the constructor to this:

 MyCommand = new DelegateCommand(() => { MyJobASync()});  

and in your method:

private async Task MyJobASync()
{
   // your method
}
0
source

Source: https://habr.com/ru/post/1016248/


All Articles