可观察的序列,它会轮询存储库,直到返回有效值

时间:2015-12-03 11:56:59

标签: c# .net asynchronous system.reactive reactive-programming

我必须轮询数据库,直到它包含有效的数据。

要做到这一点,我有一个应该每隔n秒查询一次的存储库,以获得我自己的实体,称为DestinationResponse

class DestinationResponse 
{
     bool HasDestination { get; set; }
     bool Destination { get; set; }
}

当DestinationResponse的属性HasDestination改为true时,会返回Destination

所以,我的可观察序列应该得到所有响应等待HasDestination=true的响应。它基本上等待HasDestination设置为true的响应。发生这种情况时,它会返回它并完成序列。它最多只会推送一个元素!

我目前的做法是:

var pollingPeriod = TimeSpan.FromSeconds(n);

var scheduler = new EventLoopScheduler(ts => new Thread(ts) {Name = "DestinationPoller"});

var observable = Observable.Interval(pollingPeriod, scheduler)                
    .SelectMany(_ => destinationRepository.GetDestination().ToObservable())
    .TakeWhile(response => !response.HasDestination)
    .TakeLast(1)
    .Select(response => response.Destination);

我知道我错了,主要是因为即使最后一次调用GetDestination还没有完成,Interval调用也会继续生成。

注意: repository.GetDestination()返回Task<DestinationResponse>,它实际上会查询数据库。

2 个答案:

答案 0 :(得分:2)

Database polling with Reactive Extensions的答案与您的示例代码合并,我认为可以为您提供所需内容。

var pollingPeriod = TimeSpan.FromSeconds(n);

var scheduler = new EventLoopScheduler(ts => new Thread(ts) {Name = "DestinationPoller"});

var query = Observable.Timer(pollingPeriod , scheduler)
    .SelectMany(_ => destinationRepository.GetDestination().ToObservable())
    .TakeWhile(response => response.HasDestination)
    .Retry()    //Loop on errors
    .Repeat()  //Loop on success
    .Select(response => response.Destination)
    .Take(1);

答案 1 :(得分:0)

此代码可能是我想要的查询。你觉得怎么样?

private IObservable<Destination> CreateOrderDestinationObservable(string boxId, int orderId)
{
    var pollingPeriod = TimeSpan.FromSeconds(DestinationPollingDelay);
    var scheduler = new EventLoopScheduler(ts => new Thread(ts) {Name = "DestinationPoller"});

    var observable = Observable.Timer(pollingPeriod, scheduler)
        .SelectMany(_ => externalBridgeRepository.GetDestination(boxId, orderId).ToObservable())
        .Where(response => response.HasDestination)
        .Retry()
        .Repeat()
        .Take(1)
        .Select(response => response.Destination);

    return observable;
}