c#中不可重入的可观察量

时间:2017-09-14 13:14:10

标签: c# async-await system.reactive

考虑以下方法:

如果我将黑客放置到位,我的单元测试会立即完成,并且“可观察到没有数据”。

如果我拿出黑客,有多个线程都试图同时登录 主机服务不允许

如何确保在任何给定时间点只有一个 生成 observables。

    private static object obj = new object();
    private static bool here = true;
    public IObservable<Party> LoadAllParties(CancellationToken token)
    {
        var parties = Observable.Create<Party>(
            async (observer, cancel) =>
            {
                // this is just a hack to test behavior
                lock (obj)
                {
                    if (!here)
                        return;
                    here = false;
                }
                // end of hack.
                try
                {
                    if (!await this.RequestLogin(observer, cancel))
                        return;

                    // request list.
                    await this._request.GetAsync(this._configuration.Url.RequestList);
                    if (this.IsCancelled(observer, cancel))
                        return;

                    while (!cancel.IsCancellationRequested)
                    {
                        var entities = await this._request.GetAsync(this._configuration.Url.ProcessList);
                        if (this.IsCancelled(observer, cancel))
                            return;

                        var tranche = this.ExtractParties(entities);

                        // break out if it's the last page.
                        if (!tranche.Any())
                            break;

                        Array.ForEach(tranche, observer.OnNext);

                        await this._request.GetAsync(this._configuration.Url.ProceedList);
                        if (this.IsCancelled(observer, cancel))
                            return;
                    }

                    observer.OnCompleted();
                }
                catch (Exception ex)
                {
                    observer.OnError(ex);
                }
            });
        return parties;
    }

我的单元测试:

var sut = container.Resolve<SyncDataManager>();
var count = 0;
var token = new CancellationTokenSource();
var observable = sut.LoadAllParties(token.Token);
observable.Subscribe(party => count++);
await observable.ToTask(token.Token);
count.Should().BeGreaterThan(0);

1 个答案:

答案 0 :(得分:3)

我确实认为你的问题正在受到XY Problem的影响 - 代码中包含多次调用未包含的方法,这些方法可能包含重要的副作用,我觉得继续提供的信息不会导致最好的建议。

也就是说,我怀疑您不打算两次订阅observable - 一次使用明确的Subscribe来电,一次使用ToTask()来电。这肯定会解释并发调用,它们发生在两个不同的订阅中。

编辑:

如何在长度上断言(调整超时以适应):

var length = await observable.Count().Timeout(TimeSpan.FromSeconds(3));

最好是调查Rx-Testing并模拟您的依赖项。这是一个很大的话题,但this long blog post from the Rx team explains it very well这个关于TPL-Rx相互作用的答案可能有所帮助:Executing TPL code in a reactive pipeline and controlling execution via test scheduler