C# 如何在Rx.Net中使用异步累加器实现ScanAsync运算符?

C# 如何在Rx.Net中使用异步累加器实现ScanAsync运算符?,c#,asynchronous,system.reactive,state-machine,rx.net,C#,Asynchronous,System.reactive,State Machine,Rx.net,Rx.Net中的扫描操作员有签名: publicstaticiobservable扫描(此IObservable源、TAccumulate种子、Func累加器); 蓄能器是空的 Func累加器 在尝试实现具有异步状态转换的状态机模型时,我发现具有以下签名的scanascync运算符将非常有用 publicstaticiobservable扫描(此IObservable源、TAccumulate种子、Func累加器); 累加器有签名 Func累加器 理想的应用程序代码应该是这样的(类似于普

Rx.Net中的
扫描
操作员有签名:

publicstaticiobservable扫描(此IObservable源、TAccumulate种子、Func累加器);
蓄能器是空的

Func累加器
在尝试实现具有异步状态转换的状态机模型时,我发现具有以下签名的
scanascync
运算符将非常有用

publicstaticiobservable扫描(此IObservable源、TAccumulate种子、Func累加器);
累加器有签名

Func累加器
理想的应用程序代码应该是这样的(类似于普通的
Scan
操作符,不同之处在于使用异步累加器)

IObservable事件;
IObservable states=events.ScanAsync(
初始状态,
异步(先前状态,evt)=>{
var newState=等待转换同步(previousState,evt);
返回新闻状态;
});
看起来MS正在发展,但它是


相关事项:

如果通过
behavior subject
为状态建模异步状态机,并订阅可观察的事件,如下面的代码

IObservable事件;
行为主体状态=新的行为主体(初始状态);
订阅(异步e=>{
var newState=等待转换(states.Value,e);
states.OnNext(newState);
})
我想在某些情况下可能会有比赛条件

我试着用

IObservable扫描异步(
可观测源,
Func减速器,
TS(初始状态)
{
var状态=源中的m。取(1)
从减速器中的下一个状态(初始状态,m).ToObservable()
从ScanAsync中的s(source.Skip(1)、reducer、nextState)
选择s;
返回可观察。返回(初始状态)。Concat(状态);
}

但是它有时会工作,有时只是阻塞,我不知道是什么原因造成的。

您可以使用
Scan
操作符创建一个中间
IObservable
,然后使用
Concat
操作符将其展平:

public static IObservable<TAccumulate> Scan<TSource, TAccumulate>(
    this IObservable<TSource> source,
    TAccumulate seed,
    Func<TAccumulate, TSource, Task<TAccumulate>> accumulator)
{
    return source.Scan(Task.FromResult(seed), async (previousTask, item) =>
    {
        return await accumulator(await previousTask, item);
    }).Concat();
}
// Concatenates all task results, as long as the previous task terminated successfully.
public static IObservable<TSource> Concat<TSource>(
    this IObservable<Task<TSource>> sources);