There is a certain class that takes in the constructor Action<object> . But I needed to transfer there an asynchronous method (that is Func<object, Task> ). Created the successor and in the designer tried to make the following

 public MyClassAsync(Func<object, Task> execute) : base (async (o)=>await Task.Factory.StartNew(()=>execute?.Invoke(o))) { } 

Naturally emphasizes async and writes that

asynchronous method anonymous should not return void

Why should I do that?

This is not a compiler error. As far as I understand, this is just a warning that the compiler does not know for sure how to behave in such a situation. That is, my code will compile, run, but I do not know for sure how it will work.

UPD:

I'll show you something for example.

Here is https://msdn.microsoft.com/ru-ru/library/microsoft.teamfoundation.mvvm.relaycommand(v=vs.110).aspx here is the description of RelayCommand

Here is one of the designers

 RelayCommand(Action<Object>, Predicate<Object>) 

But https://msdn.microsoft.com/ru-ru/library/microsoft.teamfoundation.mvvm.asyncrelaycommand(v=vs.110).aspx AsyncRelayCommand : RelayCommand

and here is the corresponding constructor

 AsyncRelayCommand(Func<Object, Task>, Predicate<Object>, Boolean) 

Unfortunately, I do not know where to look at the source of this. But something tells me that if I pass o => Task.Factory.StartNew(...) into the base constructor, as suggested in the comments, I will get an unmanaged task that I won’t be able to find out.

UPD2

So ultimately I should get 2 classes

RelayCommand and AsyncRelayCommand : RelayCommand

Implied to use them so

 public RelayCommand SomeCommand {get;set;} public RelayCommand SomeAsyncCommand {get;set;} public Ctor() { SomeCommand = new RelayCommand(AnyMethod, Predicate); SomeAsyncCommand = new AsyncRelayCommand(AnyMethodAsync, Predicate); } async Task AnyMethodAsync() { await SomeTask; UIMethod(); // я должен быть уверен, что этот метод выполнится в UI потоке. Конечно, предполагается, что задача сработала посредством взаимодействия пользователя с интерфейсом (по нажатию кнопки или хоткея или еще как) } 

It’s AsyncRelayCommand to define a constructor for AsyncRelayCommand , since the basic constructor is supposed to be used for RelayCommand , but it takes an Action (well, or Action<object> , but this is already a matter of variability), and the async method should be of type Func<Task> (or Func<object,Task> )

  • Comments are not intended for extended discussion; conversation moved to chat . - Nofate

1 answer 1

There is no need to create a separate class to run the asynchronous method in the UI stream. You can use the usual RelayCommand for this if you change the return value to void:

 public RelayCommand SomeAsyncCommand { get; } = new RelayCommand(AnyMethodAsync, Predicate); async void AnyMethodAsync() { await SomeTask; UIMethod(); } 

If returning a Task from a method is fundamental, then when you call a method from a command, you can simply ignore it:

 public AsyncRelayCommand(Func<object, Task> execute) :base (o => execute(o)) { } 
  • On async void I get a warning that atat do so! As far as I know, the async void method cannot be waited through await . Are there any other restrictions? I have to be sure that this will not create surprises. - iRumba
  • @iRumba stackoverflow.com/questions/12144077/… - Vladislav Khapin
  • @iRumba should not be such a warning. async void is a standard solution for event handlers. - Pavel Mayorov
  • @iRumba has more exception handling features in such methods. Do not forget to hang up the handler of uncaught exceptions when starting the application - then there will be no surprises. - Pavel Mayorov