C# 一次强制执行一个异步可观察

C# 一次强制执行一个异步可观察,c#,.net,task-parallel-library,system.reactive,C#,.net,Task Parallel Library,System.reactive,我正在尝试使用Observable.fromsync将一些TPL async集成到一个更大的Rx链中,如下面的小示例: using System; using System.Reactive.Linq; using System.Threading.Tasks; namespace rxtest { class Program { static void Main(string[] args) { MainAsync().

我正在尝试使用
Observable.fromsync
将一些TPL async集成到一个更大的Rx链中,如下面的小示例:

using System;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace rxtest
{
    class Program
    {
        static void Main(string[] args)
        {
            MainAsync().Wait();
        }

        static async Task MainAsync()
        {
            await Observable.Generate(new Random(), x => true,
                                      x => x, x => x.Next(250, 500))
                .SelectMany((x, idx) => Observable.FromAsync(async ct =>
                {
                    Console.WriteLine("start:  " + idx.ToString());
                    await Task.Delay(x, ct);
                    Console.WriteLine("finish: " + idx.ToString());
                    return idx;
                }))
                .Take(10)
                .LastOrDefaultAsync();
        }
    }
}
然而,我注意到,这似乎是同时启动所有异步任务,而不是一次只启动一个,这会导致应用程序的内存使用激增。
SelectMany
的作用似乎与
Merge
没有什么不同

在这里,我看到如下输出:

start:  0
start:  1
start:  2
...
我想看看:

start:  0
finish: 0
start:  1
finish: 1
start:  2
finish: 2
...

如何实现这一点?

SelectMany
更改为
Select
,使用
Concat

    static async Task MainAsync()
    {
        await Observable.Generate(new Random(), x => true,
                                  x => x, x => x.Next(250, 500))
            .Take(10)
            .Select((x, idx) => Observable.FromAsync(async ct =>
            {
                Console.WriteLine("start:  " + idx.ToString());
                await Task.Delay(x, ct);
                Console.WriteLine("finish: " + idx.ToString());
                return idx;
            }))
            .Concat()
            .LastOrDefaultAsync();
    }
编辑-我将Take(10)向上移动,因为Generate不会阻塞-所以它停止了这种运行


Select
将每个事件投影到一个表示将在订阅时启动的异步任务的流中
Concat
接受一个流,并在前一个流完成时订阅每个连续的子流,将所有流连接成一个单一的平面流。

那么您想用并行库编写串行代码吗?@AustinSalonen这些工具设计用于异步代码,而不仅仅是并行代码。并非所有异步代码都需要并行化。他在这里使用了完全合适的工具。@Servy:我只是想看看这里到底发生了什么。您只需阻塞
fromsync
调用即可满足此场景。这可能不正确,但看起来这正是他想要的。@AustinSalonen说,这不会保持异步,而且使用这些工具是不恰当的。鉴于OP正在使用这些工具,他们显然希望找到解决这个问题的异步解决方案。找到一个完全同步的解决方案是非常简单的。@AustinSalonen如果你认为一个问题不够清楚,要求澄清将比在对方不知道自己在做什么的情况下留下尖刻的评论更有成效。编辑以添加解释,再加上一个小的优化,以防止生成运行失控。或者,
.Take(1).Repeat()
。实际上那就是
.Take(1).Repeat().Take(10)
,这有点傻。搞定了-如果你想要某种程度的并行性,使用
合并(anInt)
,而不是这里的Concat