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()))