我正在尝试异步填充我的缓存
static ConcurrentDictionary<string, string[]> data = new ConcurrentDictionary<string, string[]>();
public static async Task<string[]> GetStuffAsync(string key)
{
return data.GetOrAdd(key, async (x) => {
return await LoadAsync(x);
});
}
static async Task<string[]> LoadAsync(string key) {....}
但这给了我错误:
无法将异步 lambda 表达式转换为委托类型“System.Func”。
异步 lambda 表达式可能返回 void、Task 或 Task,其中任何一个都不能转换为“System.Func”。
据我了解,这是因为GetOrAdd()
不是异步的。我该如何解决这个问题?
Update:
LazyAsync
评论中建议的将在我的小例子中起作用。或者,像这样的解决方法(绝对可以忍受它引入的一些开销):
public static async Task<string[]> GetStuffAsync(string key)
{
string[] d = null;
if (!data.ContainsKey(key))
d = await LoadAsync(key);
return data.GetOrAdd(key, d);
}
那么问题就变成了微软是否没有时间更新所有接口来支持异步,或者我正在尝试做一些严重错误的事情(并且ConcurrentDictionary
不应该有GetOrAddAsync()
) ?
异步方法(或 lambda)只能返回void
or Task
or Task<T>
但你的 lambda 返回string[]
因此编译器会阻止你。
await
关键字经过优化,可以在任务已完成时同步继续。因此,一种选择是将任务本身存储在字典中,而不必担心一次又一次等待完成的任务。
private static ConcurrentDictionary<string, Task<string[]>> data =
new ConcurrentDictionary<string, Task<string[]>>();
public static Task<string[]> GetStuffAsync(string key)
{
return data.GetOrAdd(key, LoadAsync);
}
当你这样做时
var item = await GetStuffAsync(...);
第一次它会(a)等待直到缓存的任务完成——之后它将同步继续。
你必须考虑什么时候会发生什么LoadAsync
失败了。因为我们正在缓存返回的任务LoadAsync
;如果失败,我们将愚蠢地缓存失败的任务。您可能需要处理这个问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)