[英]C# have async function call synchronous function or synchronous function call async function
[英]Async call within synchronous function
我正在尝试异步填充缓存
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()
不是异步的。 我该如何解决该问题?
更新: LazyAsync
建议的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);
}
然后,问题就变成了Microsoft是否没有时间更新所有接口来支持异步,或者我正尝试做一些严重错误的事情(并且ConcurrentDictionary
不应该具有GetOrAddAsync()
)?
异步方法(或lambda)只能返回void
或Task
或Task<T>
但是您的lambda返回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);
}
而当你这样做
var item = await GetStuffAsync(...);
第一次它将(a)等到缓存的Task完成-之后将同步继续。
您必须考虑在LoadAsync
失败时应该发生的情况。 因为我们正在缓存LoadAsync
返回的LoadAsync
; 如果失败,我们将愚蠢地缓存失败的任务。 您可能需要处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.