我要解决的问题是如何正确利用observe_on在不同线程上订阅多个主题,但要保持它们在原始线程上的发射顺序。主题在同一线程上被触发,我只是试图将其结果移到第二线程,同时保持彼此之间的相对顺序。
我发现,订阅一个主题并利用observe_on将结果移到另一个线程似乎可以保持预期的顺序。但是,当两个不同的主题通过observe_on订阅并集中到同一事件工作者/协调器时,它们相对于彼此的顺序似乎丢失了。 (至少使用到目前为止我尝试过的设置)
常规设置:
更具体的示例(使用了一些QT,但希望伪代码要点很清楚):
class TestThread : public QThread
{
public:
TestThread();
// Starts the thread
void run();
rxcpp::subjects::subject<int> spam_;
rxcpp::subjects::subject<bool> done_;
};
void TestThread::run() {
for (int i = 0; i < 1000; ++i) {
spam_.get_subscriber().on_next(i);
}
LOG("Firing finished");
done_.get_subscriber().on_next(true);
}
/// Main thread
// Create background thread
auto background_thread = new TestThread();
// Set up coordinator to run on one worker
rxcpp::schedulers::other_thread;
rxcpp::composite_subscription sub;
auto worker = other_thread.create_worker(sub);
auto coord = rxcpp::serialize_same_worker(worker );
thread_->spam_.get_observable()
.observe_on(coord)
.subscribe([=](int i)
{
LOG("Spam %i", i);
});
thread_->done_.get_observable()
.observe_on(coord)
.subscribe([=](bool)
{
LOG("DONE");
});
// Fire subjects on background thread
background_thread.start();
我想要达到的结果看起来像这样:
Spam 0
Spam 1
...
Firing finished // At some point the background thread is done with the loop, cool
...
Spam 45
...
Spam 999
DONE // After all spam events have fired, we see the DONE subject's event
// End of file
相反,我看到的是DONE被交错插入并被提前解雇了:
Spam 0
Spam 1
...
Firing finished // At some point the background thread is done with the loop, cool
...
Spam 45
DONE // Oh no
Spam 46
...
Spam 999
// End of file
如果spam_
和done_
主题从不同的线程被解雇,上述结果对我来说将是有意义的,因为不能确保锁定工人队列的顺序正确;谁首先收到互斥体,谁就会排在后面,这可能是混乱的。
但是,在上面的示例中,由于两个主题都从同一线程被解雇,所以我可以想象所有垃圾邮件事件在完成事件排队之前都已经排在工作线程上,因为两者之间没有线程争用。当工作人员完成了调度程序上的事件后,我会期望done_
事件总是最后完成。
这是开发人员手册中的适用报价,这让我觉得工人应该尊重订单:
worker owns a queue of pending schedulables for the timeline and has a lifetime. When the time for an schedulable is reached the schedulable is run. The queue maintains insertion order so that when N schedulables have the same target time they are run in the order that they were inserted into the queue.
我对这些整体机制有误解吗?是否存在一个计划程序设置,我可以用来在多个主题订阅之间实现一致的排队?
我发布的代码只是我尝试过的其他几种途径之一。到目前为止,还没有任何组合可以工作。
在此先感谢您的帮助或见解! 8)