Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在并发处理带有反应式扩展的流时限制缓冲_C#_Multithreading_System.reactive - Fatal编程技术网

C# 如何在并发处理带有反应式扩展的流时限制缓冲

C# 如何在并发处理带有反应式扩展的流时限制缓冲,c#,multithreading,system.reactive,C#,Multithreading,System.reactive,我有一个交错的流,我需要它 制作人 int streamCount = 3; new MyIEnumerable<ElementType>() .ToObservable(Scheduler.ThreadPool) .Select((x,i) => new { Key = (i % streamCount), Value = x }) .Subscribe(x => outputs[x.Key].OnNext(x.Value)); 这段代码的问题是,它将尽可能快地读取

我有一个交错的流,我需要它

制作人

int streamCount = 3;

new MyIEnumerable<ElementType>()
.ToObservable(Scheduler.ThreadPool)
.Select((x,i) => new { Key = (i % streamCount), Value = x })
.Subscribe(x => outputs[x.Key].OnNext(x.Value));

这段代码的问题是,它将尽可能快地读取整个可枚举项,即使输出流无法跟上。在我的例子中,枚举是一个文件流,因此这可能会导致使用大量内存。因此,如果缓冲区达到某个阈值,我希望读取被阻止。

我已经通过在生产者和消费者上使用信号量解决了这个问题,如下所示。然而,我不确定这是否被认为是一个好的解决方案(就接收合同、编程风格等而言)


CancelationToken
传递给调用
Wait()
并确保在流异常停止时取消它可能是一个好主意?

我认为您的解决方案非常合理。最大的问题(对上一个问题有一些背景知识)是,您的解决方案的“内部”现在到处都暴露出来了。只要确保在正确编写代码时,您会清理以下内容:

  • 将所有内容封装到一个公开单个方法的类中:
    IDisposable Subscribe(,Action)
    或者
    IObservable ToObservable())
    。无论是返回的订阅还是返回的可观察对象,都已经完成了所有的“工作”,即添加的
    Do
    操作等等。下面有一个字典或列表这一事实应该与用户完全无关,否则对代码的任何更改都需要到处更改

  • CancelationToken
    是个好主意,请确保在
    OnCompleted
    OnError
    上取消它,您可以使用重载来执行
    do

var outputs = Enumerable.Repeat(0, streamCount).Select(_ => new Subject<char>()).ToArray();                                                                                                     

outputs[0].ObserveOn(Scheduler.ThreadPool).Subscribe(x => Console.WriteLine("stream 0: {0}", x));
outputs[1].ObserveOn(Scheduler.ThreadPool).Subscribe(x => Console.WriteLine("stream 1: {0}", x));
outputs[2].ObserveOn(Scheduler.ThreadPool).Subscribe(x => Console.WriteLine("stream 2: {0}", x));
var semaphore = new SemaphoreSlim(MAX_BUFFERED_ELEMENTS);

// add to producer (before subscribe)
.Do(_ => semaphore.Wait());

// add to consumer (before subscribe)
.Do(_ => semaphore.Release()))