0

到目前为止,我有一个运行良好的多服务器应用程序。我有4个cpp文件。Main.cpp 构建程序。MainWindow.cpp 构造 ui 并启动(通过 buttonclick)MyServer.cpp。MyServer.cpp 创建一个线程并启动 MyThread.cpp。我的目标是在 textBrowser 上显示几个主要步骤(如“服务器启动”、“新连接”等)。

我将 MyServer.cpp 的输出通过传递emit updateUI("server started");给 mainwindow.cpp,其中输出被捕获:

    //Mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myserver.h"
#include "mythread.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::AppendToBrowser(const QString text)
{
    ui->textBrowser->append(text);
}

void MainWindow::on_startButton_clicked()
{
    MyServer* mServer = new MyServer;
    connect(mServer, SIGNAL(updateUI(const QString)), this, SLOT(AppendToBrowser(const QString)));
    mServer->StartServer();

    ui->textBrowser->setPlainText("Server Started");
}

因为连接命令就在 mainwindow.cpp 本身中,所以它工作得恰到好处。问题在 mythread.cpp 中开始“更深”一步。

我在

//MyThread.h

signals:
    void updateUI_serv(const QString text);

并在 MyServer.cpp 中将它与 MainWindow.cpp 连接起来。

    //MyServer.cpp

#include "myserver.h"
#include "mainwindow.h"

MyServer::MyServer(QObject *parent) :
    QTcpServer(parent)
{
}

void MyServer::StartServer()
{
    if(!this->listen(QHostAddress::Any,1234))
    {
        qDebug("Server Error");
    }
    else
    {
        qDebug("Server started");
    }
}

void MyServer::incomingConnection(int socketDescriptor)
{
    qDebug("new connection");


    MyThread *thread = new MyThread(socketDescriptor,this);
    MainWindow *mMain = new MainWindow;
    connect(thread, SIGNAL(updateUI_serv(const QString)),mMain ,SLOT(AppendToBrowser(const QString)));


    //flags thread for selfdeletion
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));



    //calls run
    thread->start();

    emit updateUI("thread started!");
}

// MyThread.cpp

#include "mythread.h"
#include "mainwindow.h"
#include "myserver.h"

MyThread::MyThread(int ID, QObject *parent) :
    QThread(parent)
{
    this->socketDescriptor = ID;
    emit updateUI_serv("start");
}

void MyThread::run()
{
    //thread stars here
    qDebug("Starting thread");
    socket = new QTcpSocket();
    emit updateUI_serv("hallo");
    //set socketdescriptor number
    if(!socket->setSocketDescriptor(this->socketDescriptor))
    {
        emit error(socket->error());
        return;
    }

    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);


    qDebug("client connected");

    exec();
}

void MyThread::readyRead()
{
    QByteArray Data = socket->readAll();
    QString Datain = QString::fromLatin1(Data);
    qDebug("Date in:");

    emit updateUI_serv("data in:");
    socket->write(Data);
}

void MyThread::disconnected()
{
    qDebug("Disconnected");
    socket->deleteLater();
    exit(0);
}

连接命令位于信号(来自 mythread.cpp 的 updateUI_serv)和插槽(来自 mainwindow.cpp 的 AppendToBrowser)文件的“中间”。此时,只要我尝试将数据(作为客户端通过 telnet)写入服务器应用程序,程序就会崩溃。

我也尝试将连接命令设置到主窗口和 mythread 中,但两次我都遇到了不同的问题(比如调试问题,或者文本没有显示在 textBrowser 中)。感谢到目前为止。

4

2 回答 2

0

啊,我自己弄的。我通过创建一个新函数(void forwarding(const Qstring);)解决了这个问题,并在那个函数中我用普通的emit updateUI(text);..东西发出了它,终于可以工作了!

于 2013-07-05T13:06:44.313 回答
0

最终 myServer-Object 没有在 MainThread 中运行,因此从另一个线程访问 ui 元素会使您的应用程序崩溃。

您可以通过将以下代码添加到 AppendToBrowser Slot 来确保仅显示来自 mainThread 的消息:

if( QApplication::instance()->thread() == QThread::currentThread() )
    ui->textBrowser->setPlainText("whateverTextThereShallBe");
else
    return;
    //You should not run into this else...

这个 if 部分检查调用更新的当前对象是否是 mainThread。else 部分检查错误。如果您在 else-section 中运行,则您试图将 ui-elements 更改为不是 mainThread(UI-Thread)的线程。将服务器中的 SIGNAL 连接到另一个 SIGNAL(SIGNAL->SIGNAL 连接)并在 MainWindow.cpp 中添加到 SIGNAL(SERVER) -> SLOT(MainWindow) 的连接。最终尝试与第 5 次通话。排队连接的参数(Qt::QueuedConnection IIRC)。

于 2013-07-05T10:29:58.927 回答