c# – 当缓冲区不包含任何项目时,为什么Rx缓冲区连续执行方法?

我有一个Rx Observable充当缓冲区.现在,当它获得10个项目时,或者在100毫秒之后,以先到者为准,它在订阅中执行该方法.

我注意到我的方法每100毫秒不断被调用,即使缓冲区中没有项目,这让我感到惊讶.如果它没有收到缓冲区中的任何项目,那么只需让我的方法立即返回就足够了,但我觉得奇怪的是它只是在背景中像这样生长.

为什么是这样?你怎么建议我最好处​​理这个?我是Rx的全新手,所以也许我正在做一些奇怪的事情.这是我的代码的简化版本:

private Subject<KeyValuePair<int,Action<MyData>>> serverRequests;

public MyBufferClass(IMyServer server,IScheduler scheduler)
{
    this.serverRequests = new Subject<KeyValuePair<int,Action<MyData>>>();

    this.serverRequests
        .Buffer(TimeSpan.FromMilliseconds(100),10,scheduler)
        .Subscribe(buffer => GetMultipleItemsFromServer(buffer));
}   

public void GetSingleItemFromServer(int id,Action<MyData> callback)
{
    this.serverRequests.OnNext(new KeyValuePair<int,Action<MyData>>(id,callback));
}

public void GetMultipleItemsFromServer(IEnumerable<KeyValuePair<int,Action<MyData>>> idsWithCallbacks)
{
    if (idsWithCallbacks.IsNullOrEmpty()) return;

    this.server.GetMultipleItems(idsWithCallbacks)
}

在我的测试中,如果我调用GetSingleItemFromServer 5次然后将我的TestScheduler推进1000毫秒,我认为GetMultipleItemsFromServer只会被调用一次,但它会被调用10次.

解决方法

在这种情况下,一个优雅的解决方案是在Buffer之后直接使用Where运算符来过滤掉任何空结果.像这样的东西:
stream
            .Buffer (...)
            .Where (x => x.Any())
            .Subscribe (x => {...},ex => {...});

至于为什么Buffer这样做,我想最好是展示一个空集合并让消费者选择如何处理它,而不是吞下它并否认这个机会.

另外,我不会在订阅块中调用您的服务器.我认为将任何异步操作作为Rx流组合本身的一部分更好,并将Subscribe操作限制为处理最终结果的任何轻量级操作,即更新UI,记录成功/失败等等.像这样:

(from request in serverRequests
            .Buffer (TimeSpan.FromMinutes (1))
            .Where (x => x.Any())
from response in Observable.Start(server.GetMultipleItems(...))
select response)
.Subscribe (x => {},ex => {});

这方面的优点包括

– 能够在服务器调用上使用更多Rx运算符,例如Timeout(),Retry(),Catch()等.

– 能够处理Subscribe()重载中的任何管道错误

– 使用SubscribeOn()/ ObserveOn()独立调度管道和Subscribe操作.

相关文章

在项目中使用SharpZipLib压缩文件夹的时候,遇到如果目录较深,则压缩包中的文件夹同样比较深的问题。比...
项目需要,几十万张照片需要计算出每个照片的特征值(调用C++编写的DLL)。 业务流程:选择照片...
var array = new byte[4]; var i = Encoding.UTF8.GetBytes(100.ToString(&quot;x2&quot;));//...
其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable&lt;Dic...
把.net4.6安装包打包进安装程序。 关键脚本如下: 头部引用字符串对比库 !include &quot;WordFunc....
项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.NetʿreeSp...