Convert async lambda expression to delegate type System.Func<T>?

偶尔善良 提交于 2019-11-30 03:02:28

No can do. When someone expects a Func<T> f you can assume it will be invoked with something like result = f() - i.e., it does not know about async behavior. If you cheat it by using .Result like you have - it will deadlock on UI thread because it wants to schedule the code after await (in _Fetch) on the UI thread, but you have already blocked it with .Result.

Async lambda can be passed to Action since it has no return value - or to Func<Task> or Func<Task<T>>.

Looking at your case, the GetOrCreateObject appears to be calling GetOrFetchObject. One of the GetOrFetchObject overloads accepts a Func<Task<T>>. You can try calling that method with your async lambda and see if it helps.

Stephen Cleary

YK1's answer explains why you can't treat Func<T> as asynchronous.

To fix your problem, use GetOrFetchObject instead of GetOrCreateObject. The "create" methods assume a (synchronous) creation, while the "fetch" methods work with (asynchronous) retrieval.

await CacheProvider.GetOrFetchObject<T>(key, () => _Fetch<T>(uri), cacheExpiry)

I also removed the unnecessary async/await in your lambda expression. Since _Fetch already returns Task<T>, there's no need to create an async lambda whose sole purpose is to await that task.

Something like this?

 Public Func<T> ConvertTask<T>(Task<T> task)
 {
     return ()=>task.Result;
 }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!