Есть некий класс, который принимает в конструктор Action<object>. Но мне потребовалось передать туда асинхронный метод (то есть Func<object, Task>). Создал наследника и в конструкторе попытался сделать следующее
public MyClassAsync(Func<object, Task> execute) :
base (async (o)=>await Task.Factory.StartNew(()=>execute?.Invoke(o)))
{ }
Естественно подчеркивает async и пишет что
asynchronous method anonymous should not return void
А чего мне делать то?
Это не ошибка компилятора. Я насколько понимаю это просто предупреждение о том, что компилятор не знает наверняка как себя вести в такой ситуации. То есть мой код скомпилируется, запустится, но я не знаю наверняка, как он отработает.
UPD:
Я покажу кое что для примера
Вот https://msdn.microsoft.com/ru-ru/library/microsoft.teamfoundation.mvvm.relaycommand(v=vs.110).aspx здесь описание RelayCommand
Вот один из конструкторов
RelayCommand(Action<Object>, Predicate<Object>)
А вот https://msdn.microsoft.com/ru-ru/library/microsoft.teamfoundation.mvvm.asyncrelaycommand(v=vs.110).aspx
AsyncRelayCommand : RelayCommand
и вот соответствующий конструктор
AsyncRelayCommand(Func<Object, Task>, Predicate<Object>, Boolean)
К сожалению я не знаю, где посмотреть на исходники этого. Но что-то мне подсказывает, что если в базовый конструктор передать o => Task.Factory.StartNew(...), как предложили в комментариях, то я получу неуправляемую задачу, об окончании которой не смогу узнать.
UPD2
Итак, в конечном счете у меня должны получиться 2 класса
RelayCommand и AsyncRelayCommand : RelayCommand
Подразумевается использовать их так
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 потоке. Конечно, предполагается, что задача сработала посредством взаимодействия пользователя с интерфейсом (по нажатию кнопки или хоткея или еще как)
}
Не получается определить конструктор для AsyncRelayCommand, так как предполагается использование базового конструктора для RelayCommand, а он принимает Action (ну или Action<object>, но это уже вопрос вариативности), а async метод должен быть типа Func<Task> (или Func<object,Task>)
Нет никакой необходимости создавать отдельный класс для запуска асинхронного метода в UI-потоке. Можно использовать для этого обычный RelayCommand если сменить возвращаемое значение на void:
public RelayCommand SomeAsyncCommand { get; } = new RelayCommand(AnyMethodAsync, Predicate);
async void AnyMethodAsync()
{
await SomeTask;
UIMethod();
}
Если возврат Task из метода принципиален - то при вызове метода из команды его можно попросту проигнорировать:
public AsyncRelayCommand(Func<object, Task> execute)
:base (o => execute(o))
{ }
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости