【问题标题】:Qt Object deleted but signal is not disconnectedQt 对象已删除但信号未断开
【发布时间】:2016-01-27 12:13:37
【问题描述】:

topic 中,它告诉当一个 qobject 被删除时,它的活动连接将被删除。我有一个类似下面的案例:

Work* work = new Work();//->Work derived from QObject 
Worker* worker  = new Worker(work);//->Worker derived from QThread and has the ownership of work

connect(work, SIGNAL(percentageComplete(int)), progressDialog, SLOT(setValue(int)));
connect(worker, SIGNAL(finished()),  worker, SLOT(deleteLater()));

progressDialog->show();
worker->start();

在工人的析构函数中我有:

Worker::~Worker(void){
    if(work != nullptr){
        work->deleteLater();
    }
}

我 %100 确定该工作已被删除。我可以通过断点看到它。我什至可以看到 QObjects 的析构函数调用。

但有些已删除的工作对象仍然收到“完成百分比”信号。又因为被删了,造成了暗恋。

我想问为什么即使删除了对象也没有断开信号?

Worker 的析构函数work->deleteLater();delete work; 中的第二个问题是否正确?

【问题讨论】:

  • 您应该提供一个最小的工作示例。
  • deleteLater() 应该用于延迟删除对象,因为它可能仍然需要 - 例如当你想删除它自己的插槽内的对象时。
  • “但有些已删除的工作对象仍然接收到信号“完成百分比” - 请澄清您确切看到的内容,添加崩溃的代码并添加回溯。在您的代码中,工作对象是发射 percentComplete,不接收它。如果发送方或接收方被破坏,信号/插槽连接将被破坏,所以我看不到你删除的工作人员如何发出信号。在你的情况下,删除应该是正确的。
  • 请重新阅读您自己的问题,这似乎没有意义。为什么work 会收到it's own percentageCompleted` 信号?另外,我怀疑你在做错误的线程。如果您在线程中使用QObject 实例,那么很可能您不应该覆盖QThread
  • 你们都是对的,阅读我自己的问题真的很有帮助。问题完全不同,并且与 lamdba 相关,没有自动断开连接。现在我应该怎么处理我的问题?我应该如何编辑它以使某些东西有用或至少不会令人困惑。

标签: c++ qt


【解决方案1】:

为什么不使用disconnect() 断开所有连接的插槽/信号? 你可以在析构函数中调用这个函数。Here你有类似主题的解决方案

【讨论】:

  • 这会断开与该对象信号的所有连接,而不是所有连接到该对象插槽的信号,这是此处需要的。
【解决方案2】:

我的猜测是工作对象被移动到工作线程,并且发出的信号最终会在事件循环中结束,可以稍后传递。可能你当时已经杀死了progressDialog。

【讨论】:

    【解决方案3】:

    除非你有一些自定义代码,否则直接使用QThread

    Work* work = new Work(); // no parent
    QThread* thread = new QThread();
    
    work->moveToThread(worker);
    
    connect(thread, SIGNAL(started()), work, SLOT(doSomeWork())); // add this function doSomething() in Work class which on completion should emit finished() signal
    connect(work, SIGNAL(finished()), thread, SLOT(quit())); // quit the thread
    connect(work, SIGNAL(finished()), work, SLOT(deleteLater())); // delete work after job done
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); // delete thread
    
    // if you are using c++11, do this to see Work and Thread deletion
    connect(work, &Work::destroyed, [](){ qDebug() << "Work object deleted"; });
    connect(thread, &QThread::destroyed, [](){ qDebug() << "Thread deleted"; });
    
    // start the thread now
    thread->start();
    

    See here for more info on QThread usage

    【讨论】:

      【解决方案4】:

      发生这种情况是因为有两个线程试图同时使用Work,但没有明显的同步,结果可想而知。

      你必须在主线程和工作线程之间封送Work的所有权和访问权,这样两个线程就不能以不安全的方式同时访问它。

      Worker的析构函数没有在Worker线程中执行!此外,当Worker thread 仍处于活动状态时,我没有看到任何阻止该析构函数运行的代码。请注意QThread 不是线程,而是线程句柄。这是一个欺骗性的名字。

      唉,如果没有看到重现问题的完整示例,就无法回答您的问题。

      【讨论】:

        猜你喜欢
        • 2011-03-12
        • 2019-02-12
        • 2012-05-21
        • 2012-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多