Use*_*rol 10 .net c# asynchronous async-await
我正在尝试异步填充我的缓存
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) {....}
Run Code Online (Sandbox Code Playgroud)
但这给了我错误:
无法将异步lambda表达式转换为委托类型'System.Func'.
异步lambda表达式可能返回void,Task或Task,其中任何一个都不能转换为'System.Func'.
据我所知,这是因为GetOrAdd()不是异步的.我该如何解决这个问题?
更新:
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);
}
Run Code Online (Sandbox Code Playgroud)
那么问题就变成微软没有时间更新所有接口来支持异步,或者我正在尝试做一些非常错误的事情(而且ConcurrentDictionary不应该有GetOrAddAsync())?
Sri*_*vel 23
异步方法(或lambda)只能返回void或Task或Task<T>,但你的拉姆达的回报string[],因此编译器会阻止您.
await关键字已优化为在任务已完成时同步继续.因此,一种选择是将Task本身存储在字典中,而不必担心一次又一次地等待已完成的Task.
private static ConcurrentDictionary<string, Task<string[]>> data =
new ConcurrentDictionary<string, Task<string[]>>();
public static Task<string[]> GetStuffAsync(string key)
{
return data.GetOrAdd(key, LoadAsync);
}
Run Code Online (Sandbox Code Playgroud)
而当你这样做
var item = await GetStuffAsync(...);
Run Code Online (Sandbox Code Playgroud)
第一次它将(a)等待缓存的任务完成 - 之后它将继续同步.
你必须考虑LoadAsync失败时会发生什么.因为我们正在缓存返回的任务LoadAsync; 如果失败了,我们将愚蠢地缓存失败的任务.您可能需要处理此问题.
| 归档时间: |
|
| 查看次数: |
2816 次 |
| 最近记录: |