【问题标题】:Threaded Server with QtConcurrent::run带有 QtConcurrent::run 的线程服务器
【发布时间】:2011-06-16 15:41:27
【问题描述】:

我正在尝试开发一个线程服务器,其中包含一个 run 方法,该方法将在另一个带有 QtConcurrent::run 的线程中运行。

我的第一个问题是:

我是对的,当我不创建不从 QTcpServer 继承而只使用 QTcpServer 对象的服务器时。

第二个问题:

在另一个线程中只运行一个方法是错误的吗?因为我已经学会了在 C# 和其他 Qt 示例中这样做,所以他们将当前对象放在其他线程中。

第三个问题:

为什么我会收到此消息:

QObject:无法为 位于不同线程中的父级。 (父级是 MyServer(0x1ab1ca0), 父线程是QThread(0x187a840), 当前线程是QThread(0x1acfa90)

当我启动 run 方法时。

这里是源代码:

我的服务器.h

#ifndef MYSERVER_H
#define MYSERVER_H

#include <QObject>
#include <QtNetwork/QTcpServer>
#include <QtConcurrentRun>
#include <QFuture>
#include "myclienthandle.h"

class MyServer : public QObject
{
    Q_OBJECT
public:
    explicit MyServer(QObject *parent = 0, const QString &ip = "Any", int port = 0);
    explicit MyServer(const MyServer &server);
    ~MyServer();
    QString IP() const;
    void setIP(const QString &ip);
    int Port() const;
    void setPort(int port);
    bool isAlive() const;


private:
    QTcpServer *m_qtcpserListener;
    QFuture<void> m_qftrRun;
    QString *m_qstrIP;
    int m_iPort;
    int m_iClientID;
    bool m_bRun;

    void run();

signals:
    void newConnection(MyClientHandle *clientHandle);

public slots:
    void start();
    void stop();
};

inline QString MyServer::IP() const
{
    return *m_qstrIP;
}

inline void MyServer::setIP(const QString &ip)
{
    m_qstrIP = new QString(ip);
}

inline int MyServer::Port() const
{
    return m_iPort;
}

inline void MyServer::setPort(int port)
{
    m_iPort = port;
}

inline bool MyServer::isAlive() const
{
    return m_bRun;
}

#endif // MYSERVER_H

我的服务器.cpp

#include "myserver.h"

MyServer::MyServer(QObject *parent, const QString &ip, int port) :
    QObject(parent), m_iClientID(0), m_bRun(false), m_qtcpserListener(0)
{
    setIP(ip);
    setPort(port);
}

MyServer::MyServer(const MyServer &server)
{
    MyServer(server.parent(), server.IP(), server.Port());
}

MyServer::~MyServer()
{
    if (m_qtcpserListener != 0)
        stop();
}

void MyServer::run()
{
    m_qtcpserListener = new QTcpServer(this);

    if (!m_qtcpserListener->listen(QHostAddress(IP()), Port()))
    {
        return;
    }

    while (m_bRun)
    {
        if (m_qtcpserListener->waitForNewConnection(5000))
        {
            QTcpSocket *qtcpsoNextPending = m_qtcpserListener->nextPendingConnection();
            emit newConnection(new MyClientHandle(qtcpsoNextPending));
        }
    }
}

void MyServer::start()
{
    m_bRun = true;
    m_qftrRun = QtConcurrent::run(this, &MyServer::run);
}

void MyServer::stop()
{
    m_bRun = false;
    if (m_qtcpserListener != 0 && m_qtcpserListener->isListening())
    {
        m_qtcpserListener->close();
    }
    m_qftrRun.cancel();
    m_qftrRun.waitForFinished();
}

感谢您的帮助。

【问题讨论】:

    标签: c++ multithreading qt4


    【解决方案1】:

    您的问题是您在不同的线程中运行MyServer::run 函数(通过QtConcurrent::run,但在MyServer::run 函数中,您创建了一个新的 TcpServer 并给它一个父级。在 Qt 中,一个父级在一个线程(并发线程)中创建的对象不能是另一个线程拥有的对象(MyServer 的实例所在的任何线程,可能是第一个线程)。

    如果你没有做到这一点,在与信号对象不同的线程中发出信号也会导致问题。您也可能在删除时遇到问题,因为您不应该在与拥有它的线程不同的线程中删除 QObject。

    我的建议是使用QTcpServer 的内置线程机制。当您调用listen 时,该函数将返回。然后,您可以连接到newConnection() 信号,以便在有连接挂起时收到通知,而不是等待连接(这可能会导致您认为您需要同时运行该函数)。

    【讨论】:

    • 您是指哪种内置线程机制?你是说 moveToThread() 方法吗?
    • @Paul Kreker:当我说“内置线程机制”时,我的措辞并不正确。我的意思是“内置异步能力”。将您的下一个挂起连接的检索和发送放在一个插槽中,将该插槽挂接到 m_qtcpserListener 的 newConnection 信号,然后当您想开始监听连接时只需在 m_qtcpserListener 上调用监听。那部分根本不需要穿线。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 2015-03-24
    • 1970-01-01
    相关资源
    最近更新 更多