树加载器扩展函数内部的异步函数调用
本文关键字:异步 函数调用 内部 函数 加载 扩展 | 更新日期: 2023-09-27 17:57:41
我有一个函数,它将加载节点的子级。在内部,它调用WCF异步服务进行加载。签名如下。
public void AddChildElements(Node parentElement,
Action<IEnumerable<Node>> callback)
{
}
这可以像一样使用
_nodeBuilder.AddChildElements(parentElement, (elements) =>
{
//do something with elements
});
现在我想写一个函数来扩展基于某些条件的层次结构。所以我写了一个类似的扩展函数
public static T LoadHierarchyUntilItemFound<T>(
this IEnumerable<T> sequence, Func<T, List<T>> loadaction,
Func<T, string> searchstring)
{
//...
}
loadaction参数需要节点的加载函数。用法如下
Elements.LoadHierarchyUntilItemFound(LoadChildren,
"root.UK.England.London");
问题是我将如何编写加载函数?
private List<Node> LoadChildren(Node parent)
{
// _nodeBuilder.AddChildElements(parent, here it expects a callback
//which gives the result, how to use this?);
}
简而言之,问题是如何使用回调函数来返回包装函数的结果?
如果你真的想要,可以只生成一个调用异步方法并阻塞直到返回的函数:
private List<Node> LoadChildren(Node parent)
{
var tcs = new TaskCompletionSource<IEnumerable<Node>>();
AddChildElements(parent, nodes => tcs.SetResult(nodes));
return tcs.Task.Result.ToList();
}
然而,在许多情况下,最好异步地完成整个过程,而不是同步地完成。
public static async Task<T> LoadHierarchyUntilItemFoundAsync<T>(
this IEnumerable<T> sequence, Func<T, Task<IEnumerable<T>>> loadaction,
Func<T, string> selector, string searchstring)
{
var stack = new Stack<T>(sequence);
while (stack.Any())
{
var item = stack.Pop();
if (selector(item) == searchstring)
return item;
foreach (var child in await loadaction(item))
{
stack.Push(child);
}
}
return default(T);
}
给定这样的函数,您可以使用调用它
Elements.LoadHierarchyUntilItemFound(AddChildElements,
"root.UK.England.London");