2013-08-03 3 views
0

내 주 스레드에 QDialog가 있으며 별도의 스레드에서 발생하는 일부 논리가 있습니다. 논리가 시작되면 show()에 연결된 신호가 대화 상자에 표시됩니다. 논리가 끝나면 대화 상자의 hide()에 연결된 신호가 방출됩니다. 논리가 실제로 작동하면 대화 상자가 제대로 표시되거나 숨겨집니다. 로직이 "아무것도"하지 않고 신호가 순차적으로 방출되는 경우 대화 상자가 항상 올바르게 표시되거나 숨겨지는 것은 아닙니다.QT QDialog가 신속하게 표시/숨기기를 할 때 제대로 숨기지 않습니다.

내 연결이 유사한 만들어 :

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; 
} 

논리는이 비슷합니다 다음 DataTransferer 물건을 수행 할 때

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(); 
    } 
} 

은 모든 것이 잘 작동합니다. 대화 상자가 표시되고 숨겨지면 DoStuff()를 호출 할 때마다 유령 대화 상자가 표시됩니다.

QThread :: currentThreadId()를 사용하여 대화 상자와 로직이 별도의 스레드에서 실행되고 있는지 확인했습니다.

이 경우 내 대화가 제대로 표시되지 않는 이유는 무엇입니까? 나는 적어도 수백 밀리 초 동안 항상 내 로직을 실행해야만한다 (그 해결책은 나쁘다)? 내 대화 상자가 완전히 숨겨지기 전에로드되었는지 확인하는 방법이 있습니까? 이 신호/슬롯을 다르게 처리해야합니까?

편집 : 나는 show() 대화 상자에 신호를 내린 후 QThread :: sleep (1)을 넣는 것으로 현재 사임했습니다. 나는이 해결책이 마음에 들지 않지만 그 밖의 것은 아무 것도 보이지 않았다. sleep (1)을 사용하면 대화 상자를 숨기기 전에 끝까지 올릴 수 있습니다. 나는 이것을 QThread :: msleep (10)과 함께 사용할 수 있었지만, 여전히 유령 다이얼로그가 약 6 회에 1 번 시도되었다.

show() 또는 hide()를 호출 할 때마다 QMutex 멤버를 대화 상자 논리로 사용하려고 시도했지만 작동하지 않았습니다.

모든 크로스 스레드 연결을 Qt :: BlockingQueuedConnection 및 Qt :: QueuedConnection을 사용하도록 변경했으며 두 시도 모두 성공하지 못했습니다.

대화 상자에서 연결을 설정 한 다음 슬롯을 직접 호출하는 개체로 슬롯 연결을 이동하려고 시도했지만 성공하지 못했습니다.

답변

0

내 생각에 "show"및 "hide"호출 인터레이스 때문에 문제가 발생합니다. 이를 확인하려면 세마포어를 사용하십시오. show가 끝날 때까지 객체를 잠그고 hide에서 기다립니다. 또 다른 가능성있는 (아마도 더 좋은) 해결책을 찾기 위해 여기에서 가장 많이 찬 대답을보십시오 : connecting signal/slot across different threads between QObjects

+0

작업 전후에 잠금/잠금 해제를 위해 Show()/Hide() 함수에서 잠금을 설정하는 QMutex를 사용했습니다. 성공하지 못했습니다. 또한 연결된 솔루션을 읽고 모든 논리적 연결 유형을 시도했지만 문제는 계속 발생합니다. –

0

신호를 슬롯에 연결하려면 Qt::BlockingQueuedConnection을 사용하십시오. 주 스레드의 이벤트 루프가 차단되어 있지 않은지 확인하십시오. 또한 작업자 스레드가 많은 CPU 시간을 사용하는 경우 QThread::yeldCurrentThread() 호출로 호출 할 수 있습니다.

관련 문제