“如何修复”;在Qt两定时器对一功能中,使用qmutex将qeventloop用于睡眠;

“如何修复”;在Qt两定时器对一功能中,使用qmutex将qeventloop用于睡眠;,qt,timer,deadlock,qeventloop,qmutex,Qt,Timer,Deadlock,Qeventloop,Qmutex,我有一些代码使用qtcpsocket来写和读, 写入-->睡眠-->读取; 用户界面有2个或更多的定时器来使用此功能;通过我想我运行同步;所以我添加了互斥锁来锁定它;由此产生僵局 qt4;qt5 void MainWindow::Start() { pTimer = new QTimer(this); pTimer->setInterval(100); connect(pTimer,SIGNAL(timeout()), this, SLOT(OnTimer()) )

我有一些代码使用qtcpsocket来写和读, 写入-->睡眠-->读取; 用户界面有2个或更多的定时器来使用此功能;通过我想我运行同步;所以我添加了互斥锁来锁定它;由此产生僵局

qt4;qt5

void MainWindow::Start()
{
    pTimer = new QTimer(this);
    pTimer->setInterval(100);
    connect(pTimer,SIGNAL(timeout()), this, SLOT(OnTimer()) );
    pTimer->start();
    pTimer2 = new QTimer(this);
    pTimer2->setInterval(100);
    connect(pTimer2,SIGNAL(timeout()), this, SLOT(OnTimer()) );
    pTimer2->start();
}

void MainWindow::OnTimer()
{
    FunCal();   // in my real code it will MyObj.DoSometing();
}
void MainWindow::FunCal()
{
    qDebug()<<"log in fun...";
    QMutexLocker loc(&this->_mtx);
    qDebug()<<"getted lock in fun...";
    QEventLoop loop;
    QTimer::singleShot(100, &loop, SLOT(quit()));
    loop.exec();
    qDebug()<<"log out fun...";
}
void主窗口::Start()
{
pTimer=新的QTimer(本);
pTimer->setInterval(100);
连接(pTimer,信号(timeout()),此,插槽(OnTimer());
pTimer->start();
pTimer2=新的QTimer(本);
pTimer2->设置间隔(100);
连接(pTimer2,信号(timeout()),此,插槽(OnTimer());
pTimer2->start();
}
void主窗口::OnTimer()
{
FunCal();//在我的实际代码中,它将是MyObj.DoSometing();
}
void主窗口::functal()
{

qDebug()imop的问题是由一个基本的误解引起的:

QTimer
不引入多线程。
它只是一种将特定时间后发送的事件排队的工具。

这就是为什么必须使用
QEventLoop
才能使其运行

但是,它仍然是一个确定性执行,这可能是OP代码中发生的情况:

  • pTimer->start();
    → 启动第一个计时器
  • pTimer2->start();
    → 启动第二个计时器
  • 控制流返回到
    QApplication
    的事件循环(未在代码中公开)
  • 第一个计时器到期并调用
    MainWindow::FunCal()
  • qDebug()\u mtx
    被锁定

  • qDebug()imop问题是由基本误解引起的:

    QTimer
    不引入多线程。
    它只是一种将特定时间后发送的事件排队的工具。

    这就是为什么必须使用
    QEventLoop
    才能使其运行

    但是,它仍然是一个确定性执行,这可能是OP代码中发生的情况:

    • pTimer->start();
      → 启动第一个计时器
    • pTimer2->start();
      → 启动第二个计时器
    • 控制流返回到
      QApplication
      的事件循环(未在代码中公开)
    • 第一个计时器到期并调用
      MainWindow::FunCal()
    • qDebug()\u mtx
      被锁定

    • qDebug()它的运行方式类似于“登录乐趣…”;“getted lock in fun…”;“log in fun…”您的问题不是很清楚。是否要同步函数
      FunCal()
      ,以便一次最多执行一次?它的运行方式类似于“log in fun…”;“getted lock in fun…”;“log in fun…”;你的问题不太清楚。你想同步函数
      FunCal()
      ,以便一次最多执行一次吗?@danny实际上,我的回答描述了你做错了什么,但没有解释如何做对。那是因为我在你的问题中没有认识到你的实际问题(您实际试图解决的问题)。我假设您希望基于某个计时实现一系列操作。我将使用状态的整数变量来完成此操作。超时:根据状态执行操作,设置下一个状态,重新启动计时器(可能间隔不同),并从信号处理程序返回。本质上,信号处理程序在处理后立即返回。否则,事件循环就会停止。@danny实际上,我的回答描述了你做错了什么,但没有解释如何做对。这是因为我无法在你的问题中认识到你的实际问题(您实际试图解决的问题)。我假设您希望基于某个计时实现一系列操作。我将使用状态的整数变量来完成此操作。超时:根据状态执行操作,设置下一个状态,重新启动计时器(可能间隔不同),并从信号处理程序返回。本质上,信号处理程序在处理后立即返回。否则,事件循环将暂停。
      QApplication::exec()
      QEventLoop::exec()
      QEventLoop::processEvents()
      QTimer::timerEvent()
      QTimer::timeOut()
      MainWindow::onTimer()
      MainWindow::FunCal()
      QEventLoop::exec()
      QTimer::timerEvent()
      QTimer::timeOut()
      MainWindow::onTimer()
      MainWindow::FunCal()
      QMutexLocker::QMutexLocker()
      QMutex::lock()
      
      #include <iostream>
      #include <mutex>
      #include <functional>
      #include <cassert>
      
      // a lock class
      class Lock {
        private:
          bool _lock;
      
        public:
          Lock(): _lock(false) { }
          ~Lock() = default;
          Lock(const Lock&) = delete;
          Lock& operator=(const Lock&) = delete;
      
          operator bool() const { return _lock; }
          void lock() { assert(!_lock); _lock = true; }
          void unlock() { assert(_lock); _lock = false; }
      };
      
      // a sample data class with a property
      class Object {
        private:
          bool _value; // a value
          Lock _lockValue; // a lock to prevent recursion
      
        public:
          std::function<void()> sigValueSet;
      
        public:
          Object(): _value(false) { }
          bool value() const { return _value; }
          void setValue(bool value)
          {
            if (_lockValue) return;
            std::lock_guard<Lock> lock(_lockValue);
            // assign value
            _value = value;
            // emit signal
            if (sigValueSet) sigValueSet();
          }
      };
      
      #define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
      
      int main()
      {
        DEBUG(Object obj);
        std::cout << "obj.value(): " << obj.value() << '\n';
        DEBUG(obj.sigValueSet = [&](){ obj.setValue(obj.value()); });
        DEBUG(obj.setValue(true));
        std::cout << "obj.value(): " << obj.value() << '\n';
      }