使IEnumerable方法异步
本文关键字:异步 方法 IEnumerable | 更新日期: 2023-09-27 18:28:27
我有以下节点:
class Node
{
public string Name;
public IEnumerable<Node> Children;
}
我有以下扩展方法:
public static class ExtensionMethods
{
public static IEnumerable<Node> TraverseTree(this Node root)
{
if (root.Children != null)
{
foreach (var child in root.Children)
{
var nodes = TraverseTree(child);
foreach (var node in nodes)
{
yield return node;
}
}
}
yield return root;
}
}
我想在树中搜索一个名为"Foo"的节点。为了做到这一点,我做了:
Node myNode = /* some large tree! */
var search = myNode.TraverseTree().Where(x=>x.Name == "Foo").FirstOrDefault();
我有3个目标
- 让方法
TraverseTree
以yield(IEnumerable)遍历树,这样,如果第3个节点恰好具有name="Foo",那么我就不必遍历整个树现在这种情况是真的 - 使方法
TraverseTree
在单独的线程上运行,因为它可能需要很长时间才能找到。因此,我认为TraverseTree
方法应该采用回调参数 - 最后,能够取消该操作将是一件好事。我是否也需要向该方法传递一个取消令牌
正确的方法是什么?
对不起,我忘了提到我正在使用.Net Framework 4.0
- 这已经用您的代码完成了。赞成延期执行
- 到目前为止,更简单的方法是保持方法同步,并将整个查询移动到另一个线程中
- 是的,您当然可以添加一个由遍历算法、子选择器或两者都检查的
CancellationToken
。另一种选择是让等待遍历结果的任何东西停止等待,而不是试图实际停止计算
首先,我会这样实现您的函数(注意CancellationToken
的使用)
public static IEnumerable<Node> TraverseTree(this Node root, CancellationToken token)
{
if (root.Children != null)
{
foreach (var child in root.Children)
{
if (token.IsCancellationRequested) return; //cancel if requested.
var nodes = TraverseTree(child);
foreach (var node in nodes)
{
yield return node;
if (token.IsCancellationRequested) return; //cancel if requested.
}
}
}
yield return root;
}
然后,以下是呼叫的样子:
var cts = new CancellationTokenSource();
var task = Task.Run(
() => myNode.TraverseTree(cts.Token).Where(x=>x.Name == "Foo").FirstOrDefault(),
cts.Token);
稍后,如果你想取消,你只需拨打:
cts.Cancel();