Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Linux下带ping操作的Qt线程_C++_Linux_Multithreading_Qt - Fatal编程技术网

C++ Linux下带ping操作的Qt线程

C++ Linux下带ping操作的Qt线程,c++,linux,multithreading,qt,C++,Linux,Multithreading,Qt,我正在努力完成一项看起来很简单的任务。。。但这是一场噩梦 我为Linux笔记本电脑开发了一个应用程序。在应用程序内部,我希望有一个独立的线程,可以连续ping另一台电脑(例如,每5秒一次,永远…好吧,只要笔记本电脑打开) 当然,当应用程序正在ping的PC未连接时,应用程序必须平稳工作,而无需等待ping操作返回。。。我怎样才能做到这一点 起初,我将QTimer与QProcess:execute(“ping”…)一起使用,效果很好。问题是,如果另一台电脑没有回复,我的整个应用程序和它的GUI在每

我正在努力完成一项看起来很简单的任务。。。但这是一场噩梦

我为Linux笔记本电脑开发了一个应用程序。在应用程序内部,我希望有一个独立的线程,可以连续ping另一台电脑(例如,每5秒一次,永远…好吧,只要笔记本电脑打开)

当然,当应用程序正在ping的PC未连接时,应用程序必须平稳工作,而无需等待ping操作返回。。。我怎样才能做到这一点

起初,我将
QTimer
QProcess:execute(“ping”…)
一起使用,效果很好。问题是,如果另一台电脑没有回复,我的整个应用程序和它的GUI在每次ping操作时都会冻结大约一秒钟。更改“ping”选项(例如设置“-i0.2”)以减少ping操作的等待时间没有帮助:当另一台电脑未连接时,我的应用程序会变得非常慢。如果我移除ping,当然一切都会顺利进行

因此,我决定在
QThread
中插入“ping”操作,但当我尝试按照中的第二个示例进行操作时,似乎没有任何效果:应用程序甚至没有启动

代码如下:

//Pinger.h
class Pinger : public QThread
{
Q_OBJECT  
 void run();
public:
    void setParam(const QString &urlToPing); // it sets the url to ping

signals:
    /// \brief  Signal emitted when pinging of specified url fails
    void pingFailed(int ok);
private:
    QString pingurl;
};

//Pinger.cpp
void Pinger::run()
{
    int exitCode;
    QProcess pingProc;
    while(true)
    {
        exitCode=pingProc.execute("ping",QStringList() << "-c 1" << "-i0.2" << pingurl);
        emit pingFailed(exitCode);
        sleep(5);
    }
}

// MainWindow::MainWindow
        pinga= new Pinger(); // defined in mainwindow.h as Pinger* Pinga
        pinga->setParam(ip_address);
        connect(pinga,SIGNAL(pingFailed(int)),this,SLOT(connectionLost(int)));
        connect(pinga,SIGNAL(finished()),pinga,SLOT(deleteLater()));
        pinga->start();
//Pinger.h
类Pinger:publicqthread
{
Q_对象
无效运行();
公众:
void setParam(const QString&urlToPing);//它将url设置为ping
信号:
///\ ping指定url失败时发出的简短信号
无效ping失败(int ok);
私人:
QString pingurl;
};
//Pinger.cpp
void Pinger::run()
{
int exitCode;
QProcess pingProc;
while(true)
{

exitCode=pingProc.execute(“ping”,QStringList()如果使用
QThread
,则最好避免
睡眠(5);
和循环
同时执行(true)
,因为线程无法在不终止它的情况下优雅地关闭。与其循环和阻塞睡眠,不如在前一个任务(进程执行)完成时通过单次触发计时器再次调用该周期性任务。但是,在这种情况下,应在其他成员插槽(
Pinger::doWork()中实现该逻辑
)。插槽
run()
应与其执行tread事件循环的默认实现保持一致。可以通过将
QThread::started()
信号与
Pinger::doWork()
连接来启动工作:


需要小心
QThread
删除。通常,单独删除
QThread
对象(从其
finished()
信号调用
deleteLater()
)是不好的。最好停止线程并在
main窗口中删除它

MainWindow::~MainWindow
{
    // stop the even loop
    pinga->quit();
    // wait for finishing current thread task; it can work only
    // if the thread is not blocked by while(true) with sleep
    pinga->wait();
    // delete if it is not a smart pointer
    delete pinga;
 }

也可以在主GUI线程中使用
QProcess
及其非阻塞API,而不使用
QThread
。在这种情况下,它应该通过
QProcess::start()
和连接到信号的插槽
QProcess::error()
QProcess::finished()启动
应用于启动下一次迭代。这些插槽也不应阻塞主线程,因此在上一次ping完成后,应使用
QTimer
启动下一次ping。

以下是“Qt方式”的示例编写Pinger类。请注意,不需要线程。QProcess是异步使用的,并通过Qt信号报告其状态。一旦您真正尝试Qt,您就会意识到使用线程很少是解决此类问题的正确或最自然的方法

请注意,我使用的Qt5启用了C++11支持,可以将Qt信号连接到C++11 lambdas…您可以同样轻松地用Qt4样式编写它,但它不会那么紧凑和可读

class Pinger : public QObject
{
    Q_OBJECT
public:
    Pinger(QObject *parent = 0) : QObject(parent)
    {
        //Have to do this ugliness because QProcess::finished is overloaded
        auto finishedFunc = static_cast<void(QProcess::*)(int)>(&QProcess::finished);
        connect(&m_process, finishedFunc, [this](int exitCode)
        {
            if( exitCode == 0 )
            {
                emit pingSuccess();
            }
            else
            {
                emit pingFailed(exitCode);
            }
        });
    }

    void run(const QString& hostToPing, int intervalInSeconds)
    {
        m_host = hostToPing;
        QTimer* timer = new QTimer(this);
        timer->start(intervalInSeconds * 1000);

        QObject::connect(timer, &QTimer::timeout, [this]()
        {
            if ( m_process.state() == QProcess::NotRunning )
            {
                m_process.start(QString("ping -c 1 -W 1 %1").arg(m_host));
            }
            else
            {
                qDebug() << "Cannot ping, previous ping operation still in progress!";
            }
        });
    }

signals:
    void pingSuccess();
    void pingFailed(int exitCode);

private:
    QProcess m_process;
    QString  m_host;
};
类Pinger:公共QObject
{
Q_对象
公众:
Pinger(QObject*parent=0):QObject(parent)
{
//必须这样做,因为QProcess::finished超载了
auto finishedFunc=静态_cast(&QProcess::finished);
连接(&m_进程,finishedFunc,[this](int-exitCode)
{
if(exitCode==0)
{
取得成功();
}
其他的
{
发射ping失败(exitCode);
}
});
}
无效运行(常量QString和hostToPing,整数间隔秒)
{
m_主机=主机托管;
QTimer*定时器=新的QTimer(此);
定时器->启动(间隔秒*1000);
QObject::connect(计时器和QTimer::超时,[此]()
{
if(m_process.state()==QProcess::NotRunning)
{
m_进程.start(QString(“ping-c1-w1%1”).arg(m_主机));
}
其他的
{

qDebug()我也遇到了同样的问题,通过在自己的线程中运行
ping
命令解决了这个问题。通过使用信号,我正在与非阻塞GUI交互

1) 我声明了一个Ping类,它运行Ping命令:

class Ping {
   public: 
      static bool start(QString host) {
        QStringList parameters;
        #if defined(WIN32)
           parameters << "-n" << "1";
        #else
           parameters << "-c 1";
        #endif

        parameters << host;

       int exitCode = QProcess::execute("ping", parameters);
       if (exitCode==0) {
           return true;
       } else {
           return false;
       }
    }
};

寻求调试帮助的问题(“为什么此代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现问题所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建问题。虽然问题本身非常不清楚,但我想知道,选择QT线程而不是QT线程的原因是什么标准C++线程?我编辑了我的帖子并添加了代码,我有一些问题缩进了所有的东西,我不认为你会这么快!我用Qt为我的应用程序,所以我想我会使用QT的线程。你的例子不是一个完整的,可能会有各种错误的代码,你不显示。使用QPrand实例和调用START()而不是execute()。连接到error并发出finished()信号以获取返回代码。然后不需要线程。这。对于像这样简单的事情,您不需要线程。在Qt中,如果您使用线程进行处理器密集型计算以外的任何事情,那么您就是在使用线程
Pinger pinger;
QObject::connect(&pinger, &Pinger::pingSuccess, []()
{
    qDebug() << "Host is up!";
});

QObject::connect(&pinger, &Pinger::pingFailed, [](int exitCode)
{
    qDebug() << "Host is unreachable! Ping exit code = " << exitCode;
});

pinger.run("google.com", 3);
class Ping {
   public: 
      static bool start(QString host) {
        QStringList parameters;
        #if defined(WIN32)
           parameters << "-n" << "1";
        #else
           parameters << "-c 1";
        #endif

        parameters << host;

       int exitCode = QProcess::execute("ping", parameters);
       if (exitCode==0) {
           return true;
       } else {
           return false;
       }
    }
};
class NetworkReceiver : public QObject
{
    Q_OBJECT
public:
    explicit NetworkReceiver(QObject * parent = nullptr);
    ~NetworkReceiver();

    void start() {
        while(true) {
            emit newConnectionStatus(Ping::start("google.at"));
            QThread::sleep(5);
        }
    }

signals:
    void newConnectionStatus(bool connected);

public slots:
    void startConnectionCheck() {
        QFuture<void> test = QtConcurrent::run(this, &NetworkReceiver::start);
    }

};