Разница между Fun c аноним и асин c ждут действия <T> - PullRequest
2 голосов
/ 31 января 2020

Я занимаюсь разработкой на ASP. NET Core Blazor и иногда смотрю на GitHub, чтобы чему-то научиться. Этот вопрос не имеет прямого отношения к Blazor, но я видел, как многие разработчики Blazor делают то, что я собираюсь объяснить.

Я заметил, что некоторые компоненты принимают Action<T> в качестве параметра, а другие принимают Func<T, Task>.

/* example */

public class MyComponentA : ComponentBase 
{
    [Parameter] public Action<T> OnClick {get; set;}

    //... other methods
}

public class MyComponentB : ComponentBase 
{
    [Parameter] public Func<T, Task> OnClickAsync {get; set;}

    //... other methods
}

Я понял, что вам следует связать Action<T> с без асинхронным / ожидающим методом и Func<T, Task> с асинхронным / методом . Пока все хорошо.

Однако я вижу, что кто-то используется для передачи асинхронной / ожидающей анонимной функции как Action<T>, например OnClick=@(async (item) => await Foo(item)). Иногда я передаю анонимную функцию async / await как Action, и она работает.

  • Это правильно?

  • Есть ли какой-либо побочный эффект?

  • Является ли Action<T>, который вызывает анонимную асинхронную / ожидающую функцию, асинхронный вызов?

Ответы [ 2 ]

6 голосов
/ 31 января 2020

Action<T> не допускает возвращаемого значения, и можно ожидать только методы, которые возвращают Task или Task<T>.

Поэтому, если вы передадите асинхронный метод как Action<T>, он будет всегда быть огнем и забыть.

Использование Func с Task в качестве возвращаемого значения может ожидаться в зависимости от того, как реализован метод.

5 голосов
/ 31 января 2020

Иногда я передаю анонимную асинхронную / ожидающую функцию как действие, и она работает.

Она компилируется .

Что на самом деле случается так, что async лямбда преобразуется компилятором в метод async void, а методы async void проблематичны c.

Это правильно? ? Есть ли какой-либо побочный эффект?

Возможно, это не правильно.

Если делегат - это просто "уведомление", то это по сути событие, а async void - это обычно приемлемый для событий. Вопрос в том, как Blazor узнает, что его работа выполнена. Blazor имеет SynchronizationContext; однако SynchronizationContext не обнаруживает async void обработчики . Таким образом, Blazor может решить, что его работа завершена, когда ему действительно нужно сделать больше.

Является ли действие, которое вызывает анонимную асинхронную / ожидающую функцию, асинхронным вызовом?

Да, но это async void, поэтому не выглядит асинхронным. Например, вызывающий делегат не может узнать, когда делегат завершил выполнение.

...