我想实现一个队列,它能够从多个线程中的多个生成器中获取事件/项目,并在单个线程上使用它们。 这个队列可以在一些关键的环境中工作,所以我非常关心它的稳定性。
我使用Rx功能实现了它,但我有两个问题:
以下代码使用简单的TestMethod说明了我的方法。它的输出显示所有值都来自不同的线程,但是在另一个线程上处理。
[TestMethod()]
public void RxTest()
{
Subject<string> queue = new Subject<string>();
queue
.ObserveOnDispatcher()
.Subscribe(s =>
{
Debug.WriteLine("Value: {0}, Observed on ThreadId: {1}", s, Thread.CurrentThread.ManagedThreadId);
},
() => Dispatcher.CurrentDispatcher.InvokeShutdown());
for (int j = 0; j < 10; j++)
{
ThreadPool.QueueUserWorkItem(o =>
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(10);
queue.OnNext(string.Format("value: {0}, from thread: {1}", i.ToString(), Thread.CurrentThread.ManagedThreadId));
}
queue.OnCompleted();
});
}
Dispatcher.Run();
}
答案 0 :(得分:4)
我不确定Subject
在严重多线程场景中的行为。我可以想象,在你谈论的情况下,像BlockingCollection
(及其潜在的ConcurrentQueue
)这样的东西已经很好了。并且很容易启动。
var queue = new BlockingCollection<long>();
// subscribing
queue.GetConsumingEnumerable()
.ToObservable(Scheduler.NewThread)
.Subscribe(i => Debug.WriteLine("Value: {0}, Observed on ThreadId: {1}", i, Thread.CurrentThread.ManagedThreadId));
// sending
Observable.Interval(TimeSpan.FromMilliseconds(500), Scheduler.ThreadPool)
.Do(i => Debug.WriteLine("Value: {0}, Sent on ThreadId: {1}", i, Thread.CurrentThread.ManagedThreadId))
.Subscribe(i => queue.Add(i));
你当然不想接触队列和锁。 ConcurrentQueue
实现非常出色,并且肯定能够有效地处理您正在讨论的大小队列。
答案 1 :(得分:3)
看看EventLoopScheduler
。它内置于RX,我认为它可以做你想要的一切。
你可以使用任意数量的observable,调用.ObserveOn(els)
(els
是你的EventLoopScheduler
的实例),你现在正在将多个observable从多个线程编组到一个线程上将每个来电排队等候OnNext
。