Чтение этого сообщения в блоге о некоторых ошибках С# 5 async/await. Он упоминает в Gotcha # 4 нечто довольно глубокое и о котором я раньше не думал.
Вкратце, он охватывает сценарий, в котором у вас есть метод с двумя перегрузками, который принимает Action и тот, который принимает Func<Task> (например, Task.Run). Эта проблема коренится в аргументе о том, что методы async void должны использоваться только для обработчиков событий, при этом сообщение затем переходит к изображению следующего сценария. Что делает компилятор, когда с помощью лямбда-функции, такой как следующая, можно скомпилировать оба Func<Task> и Action:
Task.Run(async () => {
await Task.Delay(1000);
});
Поскольку Task.Run имеет подписи как Task.Run(Func<Task>), так и Task.Run(Action), какой тип представляет собой асинхронную анонимную функцию, скомпилированную? A async void или Func<Task>? У меня возникает ощущение, что он скомпилируется до async void только потому, что его не-общий тип, однако компилятор С# может быть умным и давать предпочтение Func<Task>.
Также есть способ явно объявить, какую перегрузку я хочу использовать? Я знаю, что могу просто создать новый экземпляр Func<Task> и передать там функцию async lambda, но он все равно будет скомпилирован до async void, а затем передаст это в конструктор Func<Task>. Каков идеальный способ убедиться, что он скомпилирован как Func<Task>?