树加载器扩展函数内部的异步函数调用

本文关键字:异步 函数调用 内部 函数 加载 扩展 | 更新日期: 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");