gpt4 book ai didi

c++ - 为什么在多线程中没有收到发出的信号?

转载 作者:行者123 更新时间:2023-12-01 14:23:37 25 4
gpt4 key购买 nike

我有一个问题,在 QThread 对象上调用 quit 后没有收到剩余的发送信号。该场景包含 2 个附加线程(QThreadstd::thread)和主执行线程。让我们调用QThread Qstd::thread T 和主线程M.
M 中,我创建了 QQ 中的 Receiver-object R 和 Sender-object S。如果使用 S 发出,也会创建一个 std::thread T 执行一堆。

class Sender : public QObject
{
Q_OBJECT;
public:
std::vector<int> m_Sent;

Sender()
{
}

public slots:
signals:
void signal(int i);

public:
void send(int i)
{
m_Sent.emplace_back(i);
emit signal(i);
}
};


class Receiver : public QObject
{
Q_OBJECT;
public:
std::vector<int> m_Received;

Receiver()
{
}

void Connect(Sender* s)
{
connect(s, &Sender::signal, this, &Receiver::slot, Qt::QueuedConnection);
}

void Disconnect(Sender* s)
{
disconnect(s, &Sender::signal, this, &Receiver::slot);
}

public slots:
void slot(int i)
{
m_Received.emplace_back(i);
}

};

void main(int argc, char** argv)
{
QApplication app(argc, argv);
qint64 random_seed = QDateTime::currentMSecsSinceEpoch();
std::cout << "Setting random seed " << random_seed << "\n";
std::srand(random_seed);
std::unique_ptr<Receiver> R(new Receiver);
std::unique_ptr<Sender> S(new Sender);
auto actions = [&S]() {
int i = 0;
std::chrono::steady_clock::time_point current =
std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point finish =
current + std::chrono::milliseconds(100);
while (current < finish)
{
std::this_thread::sleep_for(std::chrono::microseconds(std::rand()%1000));
S->send(i++);
std::this_thread::sleep_for(std::chrono::microseconds(std::rand()%1000));
S->send(i++);
std::this_thread::sleep_for(std::chrono::microseconds(std::rand()%1000));
S->send(i++);
std::this_thread::sleep_for(std::chrono::microseconds(std::rand()%1000));
S->send(i++);
std::this_thread::sleep_until(current + std::chrono::milliseconds(17));
current = std::chrono::steady_clock::now();
}
};

std::unique_ptr<QThread> Q(new QThread());
R->moveToThread(Q.get());
R->Connect(S.get());
Q->start();
std::thread T(actions);
T.join();

// approach 1:
QMetaObject::invokeMethod(Q.get(), "quit", Qt::QueuedConnection);
Q->wait(); // never returns
// approach 2:
Q->quit();
Q->wait(); // missing events

std::cout << "Sent: ";
for(auto v : S->m_Sent)
{
std::cout << v << " ";
}
std::cout << std::endl;
std::cout << "Received: ";
for(auto v : R->m_Received)
{
std::cout << v << " ";
}
std::cout << std::endl;
}

我正在使用 VS2013 和 Qt 5.5.1 在 Windows 上工作。我用 R 中的一种计数器对其进行了测试,以跟踪接收到的信号。在调试时,我检查了所有的发射,所以所有的发射都应该插入到 Q 中的事件循环中。在 Q.wait() 之后,插槽的计数器与发出的信号不对应。我本以为带有剩余输入事件的事件循环是由 Q.quit()Q.wait() 处理的,但似乎并非如此,总是有一个从某一点开始切断“事件流”。我现在尝试了 4 天,通过 Qt-Docu 和谷歌找到的其他几个东西,但到目前为止没有任何建议有效。

最佳答案

我不是 100% 确定,因为文档不是很清楚,但是是什么让您认为 even 循环在退出之前处理所有未决事件?我的假设是在每个循环中都有一个“我应该退出”的检查,并且它可以在设置退出标志时丢弃一些未决事件。

为了总结下面的讨论,我建议添加一个新的信号,你可以从任何你想要的地方发出(比如从 std::thread 一旦你发出了你想要的一切),它会进入 QThread事件循环队列并连接到QThread quit方法,以便线程在处理时退出。如果需要,您也可以避免定义新信号。

您的代码看起来像(未测试):

Sender S = new Sender();
QThread Q = new QThread();
Receiver R = new Receiver();
R->moveToThread(Q);
connect(S, &Sender::signal, R, &Receiver::slot, Qt::QueuedConnection);

Q->start();
while(!Q.isRunning())
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

std::thread T([&S](){
emit S->signal(); // only an example, several other connects are used too
})

T.join();

QMetaObject::invokeMethod(Q, "quit",
Qt::QueuedConnection);

Q.wait();

关于c++ - 为什么在多线程中没有收到发出的信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41592538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com