Преобразования асинхронных лямбда-выражение в делегат типа 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
этой задачи.