如何防止 运行 多次扫描?

How to prevent Scan from running multiple times?

例如

var subject = new Subject<int>();
var test = subject.Scan(0, (x, y) => {
    Console.WriteLine("scan");
    return x + 1;
});
test.Subscribe(x => Console.WriteLine("subscribe1"));
//test.Subscribe(x => Console.WriteLine("subscribe2"));
Observable.Range(0, 1).Subscribe(subject);
Console.WriteLine("done");
Console.Read();

输出为

scan
subscribe1
done

但是如果你取消注释第二个订阅输出是

scan
subscribe1
scan
subscribe2
done

为什么扫描 运行 两次,我该如何预防? 所以输出应该是

scan
subscribe1
subscribe2
done

我使用 Subject 来积累不同的 Observables。然后我使用 Scan 方法更新模型,然后我在不同的地方需要订阅模型更新。也许不使用 Subject 有更好的解决方案?

您看到的问题是 Subject 是一个热可观察对象,而 Scan 会在您每次订阅它时创建一个新的冷可观察对象。

尝试在主题之前移动扫描

var subject = new Subject<int>();
subject.Subscribe(x => Console.WriteLine("subscribe1"));
subject.Subscribe(x => Console.WriteLine("subscribe2"));
Observable.Range(0, 1).Scan(0, (x, y) => {
    Console.WriteLine("scan");
    return x + 1;
}).Subscribe(subject);
Console.WriteLine("done");
Console.Read();

你也可以不用 Subject:

var test = Observable.Range(0, 1).Scan(0, (x, y) => {
    Console.WriteLine("scan");
    return x + 1;
}).Publish();

test.Subscribe(x => Console.WriteLine("subscribe1"));
test.Subscribe(x => Console.WriteLine("subscribe2"));
test.Connect();

Console.WriteLine("done");
Console.Read();

Hot vs Cold Observables

尝试使用 Observable.Publish 获得 IConnectableObservable<T>

var subject = new Subject<int>();
var test = subject
    .Scan(0, (x, y) => {
        Console.WriteLine("scan");
        return x + 1;
    })
    .Publish();
test.Subscribe(x => Console.WriteLine("subscribe1"));
test.Subscribe(x => Console.WriteLine("subscribe2"));
test.Connect();
Observable.Range(0, 1).Subscribe(subject);
Console.WriteLine("done");
Console.Read();

输出:

scan
subscribe1
subscribe2
done

Publish 将冷的 Scan observable 变成热的 observable,当调用 Connect 时开始发射值。