1

メインスレッドに QDialog があり、別のスレッドで発生するロジックがあります。ロジックが開始されると、ダイアログの show() に接続されたシグナルが発行されます。ロジックが終了すると、ダイアログの hide() に接続されたシグナルが発行されます。ロジックが実際に機能すると、ダイアログは適切に表示/非表示になります。ロジックが「何も」せず、信号が順番に発行されるだけの場合、ダイアログは常に適切に表示/非表示になるとは限りません。

私の接続は次のようになります。

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget* parent = 0) :
        Ui(new Ui::MainWindowUi),
        Transferer(new DataTransferer()),
        TransferProgress(this),
        TransferThread()
    {
        Ui->setupUi();
        connect(&Transferer, SIGNAL(Begin()), &TransferProgress, SLOT(show()));
        connect(&Transferer, SIGNAL(End()), &TransferProgress, SLOT(hide()));

        Transferer.moveToThread(&TransferThread);
        TransferThread.start();

        Transferer.DoStuff(true);
    }

    virtual ~MainWindow()
    {
        TransferThread.quit();
        TransferThread.wait(1000);            

        delete Ui;
        Ui = NULL;
    }

private:
    Ui::MainWindowUi* Ui;
    DataTransferer Transferer;
    TransferProgressDialog TransferProgress;
    QThread TransferThread;
}

ロジックは次のようになります。

class DataTransferer : public QObject
{
    Q_OBJECT
public:
    DataTransferer(QObject *parent) : QObject(parent) {}
    virtual ~DataTransferer() {}

    void DoStuff(bool dontDoStuff)
    {
        emit Start();
        if (!dontDoStuff)
        {
            QThread::sleep(1);
        }
        emit End();
    }
}

DataTransferer が処理を行うと、すべてが正常に機能します。ダイアログが立て続けに表示されたり非表示になったりすると、ほぼ 1 回おきに DoStuff() を呼び出してゴースト ダイアログが表示されます。

QThread::currentThreadId() を使用して、ダイアログとロジックが別のスレッドで実行されていることを確認しました。

この場合、ダイアログが適切に非表示にならないのはなぜですか? ロジックを常に少なくとも数百ミリ秒実行するように強制する必要がありますか (その解決策は悪いです)。ダイアログを非表示にする前に、ダイアログが完全に読み込まれていることを確認する方法はありますか? これらのシグナル/スロットを別の方法で処理する必要がありますか?

編集:私は現在、ダイアログを表示するシグナルを発行した後、QThread::sleep(1) を配置することに辞任しました。私はこの解決策が好きではありませんが、他に何も機能していないようです。sleep(1) を使用すると、ダイアログを非表示にする前に、ダイアログを最後まで表示できます。これを QThread::msleep(10) で動作させることもできましたが、それでも 6 回の試行で約 1 回ゴースト ダイアログが表示されました。

show() または hide() を呼び出すたびに、ダイアログ ロジックでメンバー QMutex を使用しようとしましたが、これは機能しませんでした。

Qt::BlockingQueuedConnection と Qt::QueuedConnection を使用するようにすべてのクロススレッド接続を変更しましたが、どちらの試行も成功しませんでした。

スロット接続をダイアログから接続を設定するオブジェクトに移動してから、スロットを直接呼び出してみましたが、それも成功しませんでした。

4

3 に答える 3

0

Qt::BlockingQueuedConnection信号をスロットに接続するために使用します。メイン スレッドのイベント ループがブロックされていないことを確認してください。また、ワーカー スレッドが多くの CPU 時間を使用する場合は、call を呼び出すことができQThread::yeldCurrentThread()ます。

于 2013-08-04T09:17:35.977 に答える