我有一个'生产者'对象,它会逐步调查一些数据,并根据队列中下一个数据项发出各种信号。
这些信号中的每一个一次最多由一个“消费者”对象处理(在将生产者的信号附加到另一个消费者之前,需要断开其插槽)。
如果消费者方面的处理因任何原因失败,则必须停止对队列的处理,因为没有必要继续处理它。
让生产者知道的最佳方法是什么,由于特殊条件,不需要进一步处理?由于消费者有一个指向生产者的指针,我想,可能有多种方式,只是我不确定它们是否是竞争条件安全的(我不知道我是否可以依赖于订单发射/处理哪些信号。
我能想到的两种方式:
我想知道在以下情况下这些解决方案是否可行:
简而言之,我必须绝对确定,如果消费者报告错误,则不会进行额外的处理。
正如你可能猜到的那样,我对这些事情的Qt习语并不十分熟悉。
答案 0 :(得分:2)
你有几个相互关联的问题。
对我而言,最重要的问题与使用线程的信号/插槽有关。
在单个线程中使用信号/插槽时,Qt默认采用AutoConnection或“直接”连接。在直接连接模式下,信号/插槽几乎完全像回调函数。这意味着发出信号的函数基本上执行子程序调用。
跨线程传输信号/插槽时,默认情况下Qt默认采用QueuedConnection。这里发生的事情很复杂。顺序是 -
知道这一点,回到原来的问题,如何知道插槽功能何时停止处理? Qt没有一个成语,我知道如何传回这些信息。但是Qt信号/槽的成语是信令线程应该对槽功能如何或连接类型是什么一无所知。
所以我的建议是通过指向要处理的数据的指针传递数据。在数据中,我会添加两个字段 -
使用这种方法 - - 没有理由调用线程必须具有信令线程的任何直接知识。 - 如果你从单线程或多线程转发,这个结构中什么都不需要改变。
希望这有助于解决您的问题。这是我们目前在我们的商店中使用的方法。
答案 1 :(得分:1)
这个成语不是特定于qt的。我请求你提出的第二种可能性的变体。但是,您不需要为答案注册信号/插槽对,只需传递一个将由生产者处理的回调,但可能在消费者的线程上。例如:
// this answer might arrive on Consumer's thread...
void Producer::ProcessAnswer(bool pShouldStop) {
// mShouldStopProcessing is shared among threads
if (mShouldStopProcessing) return;
if (pShouldStop) {
// double checking pattern...
if (!mShouldStopProcessing) {
Lock lock;
if (!mShouldStopProcessing) {
// this notifies producer to stop processing
mShouldStopProcessing = true;
}
}
}
}
void Producer::ProcessData() {
for (DataContainer::iterator tCurrent = mData.begin();
tCurrent != mData.end();
++tCurrent) {
if (mShouldStopProcessing) break;
else {
// emit signal here:
OnDataProcessing
(*tCurrent, std::bind(std::mem_fn(&Producer::ProcessAnswer), this));
}
}
}
在消费者方面,您需要:
void ProcessData(Data& pData, std::function<void (bool)> pCallback) {
// process data here...
bool tResult = //...;
pCallback(tResult);
}