Преобразования асинхронных лямбда-выражение в делегат типа System.Фанк?
у меня есть асинхронный метод в переносимая библиотека классов с этой подписью:
private async Task<T> _Fetch<T>(Uri uri)
он извлекает ресурс, который отбрасывается как конкретный тип T.
Я работаю с сторонней библиотекой кэша (Akavache), что требует Func<T> в качестве одного из параметров и попытались сделать это таким образом:
await this.CacheProvider.GetOrCreateObject<T>(key,
async () => await _Fetch<T>(uri), cacheExpiry);
это приводит к ошибке:
не удается преобразовать лямбда-выражение в делегат асинхронного тип '
System.Func<T>'. Асинхронное лямбда-выражение может возвращатьvoid,TaskилиTask<T>, ни один из которых не конвертируется в'System.Func<T>'.
Я пробовал различные перестановки Func<T> назначение без везения, единственный способ заставить код работать-это сделать Func<T> блокирование:
await this.CacheProvider.GetOrCreateObject<T>(key,
() => _Fetch<T>(uri).Result, cacheExpiry);
который блокирует мое приложение.
есть указания, где я сбиваюсь с пути?
3 ответов
не могу. Когда кто-то ожидает Func<T> f вы можете предположить, что он будет вызван, с чем-то вроде result = f() - т. е. он не знает об асинхронном поведении. Если вы обманываете его с помощью .Result как у вас есть-это будет взаимоблокировка в потоке пользовательского интерфейса, потому что он хочет запланировать код после await (в _Fetch) в потоке пользовательского интерфейса, но вы уже заблокировали его с помощью .Result.
асинхронная лямбда может быть передана в Action поскольку он не имеет возвращаемого значения - или Func<Task> или Func<Task<T>>.
глядя на ваш случай,GetOrCreateObject кажется, вызывает GetOrFetchObject. Один из GetOrFetchObject перегрузки принимает Func<Task<T>>. Вы можете попробовать вызвать этот метод с помощью асинхронной лямбды и посмотреть, поможет ли это.
YK1 это объясняет, почему вы не можете относиться к Func<T> как асинхронный.
чтобы устранить проблему, используйте GetOrFetchObject вместо GetOrCreateObject. Методы " create "предполагают (Синхронное) создание, в то время как методы" fetch " работают с (асинхронным) извлечением.
await CacheProvider.GetOrFetchObject<T>(key, () => _Fetch<T>(uri), cacheExpiry)
я также удалил ненужное async/await в лямбда-выражение. С _Fetch возвращает Task<T>, нет необходимости создавать элемент async лямбда, чья единственная цель это await этой задачи.