Cra*_*SFT 27 c# async-await c#-5.0 portable-class-library
我有一个带有此签名的可移植类库中的异步方法:
private async Task<T> _Fetch<T>(Uri uri)
Run Code Online (Sandbox Code Playgroud)
它获取一个被回送为具体类型T的资源.
我正在使用第三方缓存库(Akavache),它需要一个Func<T>参数作为其中一个,并试图以这种方式这样做:
await this.CacheProvider.GetOrCreateObject<T>(key,
async () => await _Fetch<T>(uri), cacheExpiry);
Run Code Online (Sandbox Code Playgroud)
这会导致错误:
无法将异步lambda表达式转换为委托类型'
System.Func<T>'.异步lambda表达式可能会返回void,Task或者Task<T>没有一个可以转换为'System.Func<T>'.
我已经尝试了各种Func<T>不带任何运气的排列,我能让代码工作的唯一方法就是Func<T>阻塞:
await this.CacheProvider.GetOrCreateObject<T>(key,
() => _Fetch<T>(uri).Result, cacheExpiry);
Run Code Online (Sandbox Code Playgroud)
哪个死了我的应用程序.
关于我误入歧途的任何指示?
YK1*_*YK1 20
没有办法.当有人期望Func<T> f你可以假设它会被调用类似的东西 result = f()- 也就是说,它不知道异步行为.如果你.Result像你一样使用它来欺骗它- 它将在UI线程上死锁,因为它想要在UI线程之后await(在_Fetch中)安排代码,但是你已经用它阻止了它.Result.
异步lambda可以传递给Action它,因为它没有返回值 - 或者是Func<Task>或Func<Task<T>>.
看着你的情况,GetOrCreateObject似乎在呼唤GetOrFetchObject.其中一个GetOrFetchObject重载接受a Func<Task<T>>.您可以尝试使用异步lambda调用该方法,看看它是否有帮助.
YK1的答案解释了为什么你不能将其Func<T>视为异步.
要解决您的问题,请使用GetOrFetchObject而不是GetOrCreateObject."create"方法假定(同步)创建,而"fetch"方法使用(异步)检索.
await CacheProvider.GetOrFetchObject<T>(key, () => _Fetch<T>(uri), cacheExpiry)
Run Code Online (Sandbox Code Playgroud)
我还删除了lambda表达式中不必要的async/ await.由于_Fetch已经返回Task<T>,因此不需要创建一个asynclambda,其唯一目的是执行await该任务.
| 归档时间: |
|
| 查看次数: |
17565 次 |
| 最近记录: |