【问题标题】:Qt Event processing problem due to QWaitCondition由于 QWaitCondition 导致的 Qt 事件处理问题
【发布时间】:2011-06-17 21:06:00
【问题描述】:

我正在开发一个多线程 QT 项目。主要问题出在串行控制器类上。该类使用 QMutex 和 QWaitCondition 来同步写入和读取方法。

问题是由于父级中的 qwaitcondition 等待方法导致子级中的信号阻塞。一旦wait方法返回,就会发出子类中的信号(接收者也是子类)。

我认为这种方法(qwaitcondition - wait)会阻止我整个应用程序中的任何信号发射。

问题是这样的:

constructor()
{
    anotherclass = new MyClass;
}
void run()
{
   forever
   {
       if(readmethod())
            waitcondition.wakeall();
   }
}

void method1()
{
      sendpacket();
      mutex.lock();
      if(waitcondition.wait(&mutex,10000))
         //somecode;

      mutex.unlock();
}

class MyClass
{
   someObject sobj;
    MyClass()
    {
        connect(sobj,SIGNAL(somesignal),this,SLOT(someslot));
    }

    void someslot()
    {
        //some code
    }
}

只有当 qwaitcondition 由于超时(本例中为 10 秒)返回时,才会调用我的名为 someslot 的插槽。

我只想在这个类中使用互斥锁和 qwaitcondition,而不是在整个应用程序中。我试图在主线程中实例化子类,但我得到了相同的行为。

概念测试

我做了一个测试项目,并在这个链接上发布了它: testwaitconditionproject

测试项目以这种方式工作: 等待条件在父线程中的超时等于 10 秒时启动。 子线程每 2 秒发出一个信号,内部插槽必须发出由父线程捕获的信号。一旦调用父插槽,就会将标志设置为 true。此标志应触发唤醒以完成 de waitcondition。

但不是,只有在等待条件超时后才会触发子级的内部信号。这是我的主要问题,父母等待条件阻止了我孩子的信号。

编辑:

我在测试项目中解决了这个问题,在另一个线程中调用了带有等待条件的方法。我无法复制该问题,因为对该方法的异步调用发生在线程 1 中(通过 dbus)。我想知道 dbus 调用是在线程 1 中发出的,所以当实例属于同一个线程时,我在子类中的事件不会被发出。

编辑 2:

我解决了将父级和子级放在中间类 qthread 中的问题。它们在 run 方法中被实例化,并且也使用了 exec 调用。

【问题讨论】:

  • 你是如何创建新线程的?您确定等待是在新线程中而不是主线程中吗?我发现通过设置 UI 线程和新线程的 objectName 来检查这一点,然后在各种调用中检查 thread()->objectName() 有助于验证这样的事情。
  • 我正在使用waitcondition来同步同一个线程中的两个方法,run方法和另一个异步调用的方法。子线程在其父线程的构造函数中实例化,但我试图从主线程实例化它而没有任何结果。我尝试使用 objectName 来验证它,而孩子们是另一个线程。你知道它为什么会这样吗?
  • run 方法应该在新构建的线程中运行。然后需要从不同的线程(可能是 UI 线程)调用 method1。这将导致调用 method1 的线程等待直到 run 方法将其唤醒。如果从同一个线程调用等待条件和等待,它将不起作用。你能发布一个工作样本吗?
  • Brett,我在帖子中添加了测试项目。

标签: qt mutex signals signals-slots slot


【解决方案1】:

您似乎没有运行处理事件所需的 QCoreApplication 事件循环。在 QCoreApplication::exec() 阻塞事件循环之前调用 write()。此外,在具有事件循环的线程内创建所有 QThread 对象似乎很重要(如果您想使用来自此类对象的信号)。我有你的例子,创建了额外的线程来运行 pparent(并解除阻塞 QCoreApplication::exec()),它运行良好。

【讨论】:

  • 你是对的,我在测试项目中的错误是在exec方法之前调用了write函数。实际上,这解决了测试项目中的问题。但这仅表明我无法在测试项目中复制该问题。我仔细检查了我原来的问题,它在任何其他调用之前调用了 exec 方法。关于附加线程,我并不完全清楚,你能解释一下为什么pparent需要一个附加线程来运行课程吗?我修复了在 exec 之后调用 write 方法的测试,带有一个计时器,仅用于测试目的。
  • 我为这个问题添加了一些新信息。我想我知道我的问题是什么,我正在努力解决这个问题。
  • pparent 不需要移动到单独的线程,但是 pparent->write() 是阻塞的,所以我的第一个想法是从不同的线程启动 ppthread。你用计时器做了同样的事情。我还测试了没有 QWaitCondition 的版本(我只是使用了 msleep),以确保 QWaitCondition 不是这里的问题,并且我得到了相同的结果。
  • 还有一点,请注意,如果你想从不同的线程发送信号,那么需要从具有事件循环的线程创建这样的线程对象,也许你在原来的项目中有类似的问题。
猜你喜欢
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 2012-04-20
  • 2019-08-03
相关资源
最近更新 更多