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

时间:2013-02-05 18:59:57

标签: c# asynchronous callback hierarchical-data

我有一个函数可以加载Node的子节点。在内部,它调用要加载的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?); 
   }

简而言之,问题是如何使用回调函数返回包装函数的结果?

1 个答案:

答案 0 :(得分:1)

如果你真的想要 可以只创建一个调用异步方法的函数并阻塞它直到它返回:

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");