2016-12-16 2 views
0

환경 요약 : qt로 작성된 응용 프로그램을 실행하는 장치가 있습니다. 데이터베이스 작업 (SQlite)을 처리하는 메인 스레드와 네트워킹 작업을위한 별도의 스레드 (3G를 통해)가 있습니다. 메인 스레드 이벤트 루프는 QCoreApplication :: exec에 의해 실행되고 네트워킹 작업을 처리하는 다른 스레드는 QThread :: exec에 의해 실행됩니다. Btw, 시작 후 소켓 스레드 선호도가 변경됨 (예 : moveToThread (socketThreadPtr))QTimer는 다른 루프가 커다란 루프로 인해 늦게 작동합니다.

간략한 설명 : 메인 스레드는 루프에서 사용 중이므로 데이터베이스에서 약 10k 레코드를 선택하기 위해 루프에서 약 + 30 초. 네트워크 스레드에는 만료 될 때마다 살아있는 메시지를 보내야하는 15 초 타이머가 있습니다. 문제는 timeout() 신호 슬롯이 루프가 끝난 후에 만 ​​실행된다는 것입니다.

솔루션은 지금까지 설립되었지만 만족스럽지 않습니다. 레코드를 선택하는 루프에서 QCoreApplication :: processEvents를 호출하면 문제가 해결되지만 해결 방법 대신 솔루션이 있는지 궁금합니다.

참고 : 활성 상태 메시지를 보내는 명령을 제공하는 타이머, 신호 및 슬롯은 현재 주 스레드에서 처리되지만 (읽기/쓰기는 네트워크 스레드에서 발생 함) 또한 네트워크 스레드에서 타이머를 이동했지만 기본 스레드에있는 것과 같은 결과를 얻었습니다.

+0

는 네트워크가 네트워크 스레드에 관련되어야한다. 연결된 슬롯이 네트워크 스레드의 오브젝트에도 있는지 확인하십시오. –

+0

타이머는 여전히 주 스레드에 있습니다. 첫 번째 : 소켓에 소켓을 직접 만들거나 socketdescriptor를 설정하고 QueuedConnection을 사용하여 소켓을 엽니 다. 생성자에 타이머를 만들고 객체의 movetothread를 호출하지 말고 invokeMethod 또는 대기중인 신호/슬롯 연결을 사용하여 initialize 함수를 호출하십시오. 이 함수에서 new를 사용하여 타이머를 만듭니다. 그렇지 않으면 타이머가 실제로 메인 스레드에 머무를 것입니다. –

+0

안녕 얘들 아! 빠른 답장을 보내 주셔서 감사합니다. Kevin, 타이머가 네트워크 스레드에서 완전히 이동했습니다. 네트워크 스레드의 해당 슬롯이 있습니다. Btw, 타이머가 힙에 만들어졌습니다. – ionutCb

답변

1

네트워크 스레드에서 타이머를 생성해야합니다. Qtimer가 네트워크 스레드의 구성원이기 때문에 네트워크 스레드가 주 스레드로 구성되어 자식 스레드의 스레드 선호도가 으로 설정되어 있습니다. 다음으로 네트워크를 이동했습니다. 스레드를 새로운 Qthread로 가져 오지 만 Qtimer는 어떻게됩니까? 그것은 여전히 ​​메인 스레드에 있습니다. (부모가 명시 적으로 네트워크 클래스를 정의 할 때를 제외하고, moveToThread가 Qtimer뿐만 아니라 객체의 자식에도 영향을 미친다는 점을 제외하고)

Qtimer는 네트워크 스레드로 생성해야합니다. 네트워크 스레드 슬롯 중 하나에있는 Qtimer를 Qthread :: start 신호에 연결합니다. 그래서 Qthrad의 start 메소드를 호출하면 새로운 스레드에서 슬롯이 실행되고 Qtimer가 해당 스레드에서 각각 생성됩니다.

+0

시작된 신호에 대해 생각해 본적이 없습니다. 좋은 점은 그 하나의 객체에 대한 전용 스레드입니다! –

+0

@SebastianLange가 더 자세히 설명해 주시겠습니까? –

+1

자한 다르, 네가 뭔지 알아? 나를 해결책으로 인도하는 멋진 남자. 고마워요! 결론적으로, 저는 이전에 QTimer를 이렇게 생성했습니다 : 새로운 QTimer (0), 생성자. 당신이 QTimer의 친화도에 대해 물어 본 후에 그 것이 었습니다. 그래서 저는 QTimer를 이렇게 만들었습니다 : 새로운 QTimer (this), 이것은 parent, network thread입니다. QTimer는 여전히 생성자에서 생성됩니다. moveToThread()는 객체와 객체의 유사도를 변경합니다. 아이들은 내가 실종됐다. 솔루션에 대해 충분히 명확하길 바랍니다. 그렇지 않다면 물어보십시오. – ionutCb

0

메인 스레드가 서버이고 클라이언트가 스레드로 처리되어야하는 경우 이처럼 실제로 소켓과 타이머를 전용 스레드에 만들어야합니다. 그렇지 않으면 또는 QTcpServer:::bind()을 초기화 기능에 사용하십시오.

Mainthread :

auto t = new QThread(); 
t->start(); 
auto o = new MyThreadObject(); 
o.moveToThread(t); 
o.setDescriptor(socketDesc); 
QMetaObject::invokeMethod(o, "initialize", Qt::QueuedConnection); 

MyThreadObject : 타이머 이후

class MyThreadObject : public QObject 
{ 
    Q_OBJECT 
public: 
    MyThreadObject(){...}; 
    void setDescriptor(qintptr socketdescriptor) 
    { 
    m_desc = socketdescriptor; 
    } 
public slots: 
    void initialize() 
    { 
    m_tcpSocket = new QTcpSocket(); 
    m_tcpSocket->setSocketDescriptor(m_desc); 
    //socket configuration 
    m_timer = new QTimer(); 
    //timer configuration 
    m_timer->start(); 
    } 
private: 
    QTcpSocket* m_tcpSocket; 
    QTimer* m_timer; 
    qintptr m_desc; 
} 
관련 문제