【问题标题】:Depth First Recursion with IAsyncEnumerable使用 IAsyncEnumerable 的深度优先递归
【发布时间】:2020-09-27 23:38:14
【问题描述】:

IEnumerable 中的递归主题已在 this 2010 SO Post 中介绍。我很好奇随着 .Net Core 3.X 中 IAsyncEnumerable<T> 的出现,这个故事发生了怎样的变化?具体来说:

  1. 我是否还应该像 Jon Skeet 所警告的那样担心递归地创建迭代器的资源成本,对于深层树?
  2. 在同一个 SO 帖子中,有人提供了一种“通用非递归扩展方法”来实现深度优先迭代而无需递归。如果今天应该使用相同的方法,那么 RecursiveSelect() 扩展的更新版本对于 IAsyncEnumerable<T> 是什么样的?

我的兴趣是对(远程)文件系统执行深度优先搜索,其中每次迭代都会导致其中一个远程文件被下载到本地。为此,我打算创建一个异步“生成器”(一个长度未知的迭代器),我可以使用await foreach 进行迭代。

作为一个测试用例,我首先尝试对本地目录进行深度优先搜索...将找到的文件复制到其他任意文件夹。

我想确保我有效地使用了IAsyncEnumerable

注意:即使创建大量 IAsyncEnumerable 迭代器对于深度树来说并不昂贵,但使用非递归方法仍然有意义,因为非递归方法可能能够“检查点”它的如果某些原因导致应用程序崩溃,则可以“恢复”。我不确定递归方法是否可以这样做。

【问题讨论】:

    标签: c# recursion .net-core generator .net-core-3.0


    【解决方案1】:

    同样的注意事项/解决方案应该适用于IAsyncEnumerable,您可以查看sharplab.io - 每个方法调用创建的状态机和迭代器,带有用于异步处理的额外代码(与“简单”IEnumerable with yield return 相比):

    这个方法:

    public static async IAsyncEnumerable<int> AEn()
    {
        for (int i = 1; i <= 10; i++)
        {
            await Task.Delay(1000);//Simulate waiting for data to come through. 
            yield return i;
        }
    }
    

    被编译器翻译成:

    [AsyncIteratorStateMachine(typeof(<AEn>d__0))]
    public static IAsyncEnumerable<int> AEn()
    {
        return new <AEn>d__0(-2);
    }
    

    其中&lt;AEn&gt;d__0 是编译器生成的IAsyncEnumerable 的实现。

    因此,您应该使用堆栈实现进行深度优先搜索。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      相关资源
      最近更新 更多