0

複数のクライアントが接続できるサーバーがあります。クライアントは GUI で、サーバーはコマンド ラインです。クライアントにはいくつかの機能 (接続やログインなど) があり、サーバーに送信されたときに応答を受け取る必要があります。

基本的に、QTcpSocket 関数の waitForConnection と waitForReadyRead を実行する必要があります。ただし、UI をブロックせずにこれを行う必要があります。

私がやろうと思ったことは次のとおりです。クラス(クライアント)に、すべての待機を行うQThreadを実装させます。これはメインで作成されます。

Client::Client (...)
{
    moveToThread (this); // Not too sure what this does
    mClient = new QTcpSocket (this);
    start();
}

void Client::run (void)
{
    exec();
}

void Client::connectToServer (...)
{
    mClient->connectToHost (hostname, port);
    bool status = mClient->waitForConnected (TIMEOUT);

    emit connected (status);
}

void Client::login (...)
{
    ... Similar to connectToServer ...
}

次に、GUI (ConnectToServerDialog など) を接続する準備ができたらいつでも実行します。スレッドからダイアログに「接続された信号」を接続するので、接続中または接続がタイムアウトしたときに、この信号が送信されます。

QMetaObject::invokeMethod (mClient, "connectToServer", Qt::QueuedConnection,
    Q_ARG (const QString &, hostname), Q_ARG (quint16, port));

これでアサート エラーが発生します (別のスレッドが所有するオブジェクトにイベントを送信できません)。

私がやっていることが良いアプローチであるかどうか誰か教えてもらえますか?もしそうなら、なぜ私のプログラムがクラッシュするのですか?

4

2 に答える 2

2

最良の方法は、waitForBlah() のようなメソッドを決して呼び出さないことです。イベント ループを未確定の期間待機させると、その間に GUI がフリーズする可能性が生じます。代わりに、QTcpSocket の connected() シグナルを、GUI を適切に更新するスロットに接続し、イベント ループを通常どおり継続させます。そのスロット内で接続されていることを行います。

于 2010-11-28T22:47:03.857 に答える
-1

コンストラクターでスレッドを開始することはお勧めしません。

次のように初期化します。

Client * client = new Client();
client->moveToThread(client);
client->start();

または、そのようなソリューションを使用したくない場合は、start();行の前にコンストラクターを追加しますthis->moveToThread(this);

upd: 申し訳ありませんが、最初はわかりませんでした。あなたがこの文字列を持っていることを。

于 2010-11-28T19:28:51.460 に答える