2017-07-18 11 views
0

私はC++ 11 std :: threadを使ってリクエストとレスポンスを作成し、QT lineeditをレスポンスで更新しています。 私は非GUIスレッドからQTウィジェットを更新することが違法だと読んだことがあります。 一部のコードでは、正常に動作します。 私はQThreadがQTウィジェットを更新できないと思っていました。そして、C++ 11スレッドはそれでOKです。QTウィジェットをC++ 11スレッドで更新する

void MyWidget::on_button_clicked() { 
    std::thread([this] { 
     auto req = doSomeRequest(); 
     req.Wait(); 
     auto res = req.response(); 

     ui->lineedit->setText(res.name()); 
     // emit updateName(res.name()); 
    }).detach(); 
} 

しかし、別のケースでは、それは私にsegfaultを与えます。 誰かがQTの内部で何が起こっているのか考えていますか?

 
PC: @  0x7f48d426bcda QFontEngineFT::loadGlyphSet() 
*** SIGSEGV (@0x10) received by PID 5484 (TID 0x7f48e4f39780) from PID 16; stack trace: *** 
    @  0x7f48dfde9390 (unknown) 
    @  0x7f48d426bcda QFontEngineFT::loadGlyphSet() 
    @  0x7f48d426bd39 QFontEngineFT::loadGlyphFor() 
    @  0x7f48d426d2cf QFontEngineFT::lockedAlphaMapForGlyph() 
    @  0x7f48e0a721a0 QRasterPaintEngine::drawCachedGlyphs() 
    @  0x7f48e0a74a07 QRasterPaintEngine::drawTextItem() 
    @  0x7f48e0a90905 (unknown) 
    @  0x7f48e091e988 QTextLine::draw() 
    @  0x7f48e091f79d QTextLayout::draw() 
    @  0x7f48e11ce733 QWidgetLineControl::draw() 
    @  0x7f48e1142e2b QLineEdit::paintEvent() 
    @  0x7f48e1051b78 QWidget::event() 
    @  0x7f48e11476f5 QLineEdit::event() 
    @  0x7f48e100c52c QApplicationPrivate::notify_helper() 
    @  0x7f48e1013220 QApplication::notify() 
    @  0x7f48e0266ae0 QCoreApplication::notifyInternal2() 
    @  0x7f48e104a54a QWidgetPrivate::sendPaintEvent() 
    @  0x7f48e104ab5f QWidgetPrivate::drawWidget() 
    @  0x7f48e104b8c4 QWidgetPrivate::paintSiblingsRecursive() 
    @  0x7f48e104b71a QWidgetPrivate::paintSiblingsRecursive() 
    @  0x7f48e104b71a QWidgetPrivate::paintSiblingsRecursive() 
    @  0x7f48e104b71a QWidgetPrivate::paintSiblingsRecursive() 
    @  0x7f48e104a702 QWidgetPrivate::drawWidget() 
    @  0x7f48e104b8c4 QWidgetPrivate::paintSiblingsRecursive() 
    @  0x7f48e104a702 QWidgetPrivate::drawWidget() 
    @  0x7f48e104b8c4 QWidgetPrivate::paintSiblingsRecursive() 
    @  0x7f48e104a702 QWidgetPrivate::drawWidget() 
    @  0x7f48e101b891 (unknown) 
    @  0x7f48e101baf1 (unknown) 
    @  0x7f48e103ba7f QWidgetPrivate::syncBackingStore() 
    @  0x7f48e1051c40 QWidget::event() 
    @  0x7f48e100c52c QApplicationPrivate::notify_helper() 
fish: “./aidmat ../aidmat.ini” terminated by signal SIGSEGV (Address boundary error) 

答えて

0

メインスレッド以外のスレッドからQWidgetsを更新することはできません。 C++ 11スレッドを使用して一度動作したという事実は、それを正当化するものではありません。

次のいずれかを試してみてください。

QMetaObject::invokeMethod(ui->lineedit, "setText", Q_ARG(QString, res.name()); 
// OR 
QString name = res.name(); 
QTimer::singleShot(0, ui->lineedit, [name, this](){ui->lineedit->setText(name);}); 
1

あなたは何をすべきかは、Qtのの実装に起因する未定義の動作です。実装と動作はプラットフォームによって異なります。 std :: threadクラスは、システム機能に関するラッパーです。 Qthreadとクラスとの関連付けは、標準ライブラリが何もしていないQtアーキテクチャの一部なので、std :: threadを使うことで、Qtライブラリの開発者があなたに言っていることを教えてくれませんでした。

あなたがしようとしていることをする必要がある場合は、シグナルスロットシステムを使用する必要があります。

関連する問題