2009-12-23 2 views
10

기존 코드의 일부를 내 Qt 앱으로 가져 와서 거기서 잠자기 기능을 알아 차렸습니다. 이러한 유형의 함수는 이벤트 프로그래밍에서 아무런 자리가 없다는 것을 알았습니다. 대신 무엇을해야합니까?내 Qt 앱에서 수면과 휴면을 대체하기 위해 사용할 수있는 것은 무엇입니까?

업데이트 : 생각과 피드백 후 대답은 다음과 같습니다. GUI 메인 스레드에서만 잠자기를 호출하고 GUI 스레드에서 processEvents() 또는 이벤트 루프를 기다려야하는 경우 GUI에서 동결.

+0

'sleep()'은 무엇을 위해 사용됩니까? –

+0

UDP 패킷을 보내고 응답을 받기까지 지연으로 사용됩니다. –

+0

이 QTime 솔루션은 자정에 실패하지 않습니까? –

답변

3

이벤트를 완전히 분해 할 필요는 없습니다. 내가해야 할 일은 QApplication::processEvents()을 호출하는 것입니다. 여기에서 sleep()은 GUI가 멈추는 것을 방지합니다.

12

꽤 아니지만 나는 Qt mailing list archives이 발견 : QThread의 수면 방법은 보호

,하지만 당신은 그렇게처럼 노출 될 수 있습니다 :

class SleeperThread : public QThread 
{ 
public: 
    static void msleep(unsigned long msecs) 
    { 
     QThread::msleep(msecs); 
    } 
}; 

을 그럼 그냥 전화 :

SleeperThread::msleep(1000); 

모든 스레드에서.

그러나 Qtimer를 사용하도록 코드를 리팩토링하는 것이 더 좋은 해결책입니다. 타이머를 끄면 수행 할 작업을 알 수 있도록 상태를 저장해야 할 수도 있습니다.

+0

그래, 나는 그 방법을 알고 있었고 SleeperThread 클래스가 더 나은 선택 인 것 같았지만 메인 스레드에서 수면을 사용하는 것이 이벤트 프로그래밍 연습에 어긋나는 것처럼 보이기 때문에 유효한 연습 이었는지 평가 중이다. –

+2

좋은 연습은 아닙니다. IMHO - 신호와 슬롯을 사용하는 Qt UDP 소켓 클래스를 사용해야합니다. 따라서 읽을 데이터가 있고 쓰기가 안전 할 때 알 수 있습니다. – Rob

+0

좋은 지적입니다. 그러나 지금은 이것이 내가 코드를 크게 파쇄해야한다고 생각하고 있습니다. 예를 들어. 패킷을 보내고 응답을받는 getUDPdata (COMMAND_BYTE)를 호출합니다. 다음 코드 행에서이 데이터를 사용합니다. 당신이 말한대로 할 수 있다면 나는 전체 프로그램을해야만하고 모든 일이 매우 복잡해질 것입니다. –

6

이벤트 기반 프로그래밍에서 수면이 나쁜 이유는 이벤트 기반 프로그래밍이 효과적으로 비 선점 형 멀티 태스킹의 형태이기 때문입니다. sleep을 호출하면 다른 이벤트가 활성화되어 스레드의 처리를 차단합니다.

udp 패킷에 대한 요청 응답 시나리오에서 요청을 보내고 즉시 응답을 기다립니다. Qt는 좋은 소켓 API를 가지고있어서 이벤트를 기다리는 동안 소켓이 차단되지 않도록 해준다. 이벤트는 올 때 올 것입니다. 귀하의 경우에는 QSocket :: readReady 신호가 귀하의 친구입니다.

추후에 일정 시간 동안 일정을 예약하려면 QTimer를 사용하십시오. 이렇게하면 다른 이벤트가 차단되지 않습니다.

+0

sleep 또는 usleep은 GUI가 죽은 이벤트 루프를 차단합니다. 이는 사용자가 작업을 취소하거나 응용 프로그램을 완전히 종료 할 수 없음을 의미합니다. 이를 수행하는 올바른 방법은 상태 머신 http://en.wikipedia.org/wiki/Finite-state_machine을 사용하는 것입니다. 이벤트 중심 프로그래밍의 세계에 오신 것을 환영합니다. – doron

2

QT가 내부적으로 이벤트를 처리하는 방법을 모르지만 가장 낮은 레벨의 대부분 시스템에서 응용 프로그램 수명이 이렇게 변합니다. 메인 스레드 코드는 기본적으로 루프입니다 (메시지 루프). 각 반복에서 응용 프로그램은 새 메시지를 제공하는 함수를 호출합니다. 대개 해당 기능이 차단되고 있습니다. 즉, 메시지가 없으면 기능이 반환되지 않고 애플리케이션이 중지됩니다.

함수가 반환 될 때마다 응용 프로그램에는 처리 할 새 메시지가 있습니다. 일반적으로받는 사람 (보낼 창), 의미 (메시지 코드, 예를 들어 마우스 포인터가 이동 됨) 및 일부 추가 데이터 (예 : 마우스가 좌표 24, 12 으로 이동되었습니다.).

이제 응용 프로그램에서 메시지를 처리해야합니다. OS 또는 GUI 툴킷은 보통 후드 아래에서 이것을 수행하므로 일부 검은 마법으로 메시지가 수신자에게 전달되고 올바른 이벤트 핸들러가 실행됩니다. 이벤트 처리기가 반환하면 이벤트 처리기를 호출 한 내부 함수가 반환되고 컨트롤을 주 루프로 되돌릴 때까지 호출 한 내부 함수가 반환되므로 이제는 다시 마법 메시지 검색 함수를 호출하여 또 다른 메시지. 이주기는 응용 프로그램이 종료 될 때까지 계속됩니다.

자 이제는 이벤트가 GUI 응용 프로그램에서 발생하는 이유는 수면 상태가 좋지 않음을 알기 위해이 모든 내용을 썼습니다. 메시지가 처리되는 동안 통지하면 메인 스레드가 실행 중입니다. 이벤트 핸들러는 결국 메시지 루프에 의해 호출되는 함수 일뿐입니다. 따라서 이벤트 핸들러를 잠자기 상태로 만들면 메시지 루프도 잠자기 상태가됩니다. 즉, 그 동안 응용 프로그램이 창을 다시 칠하는 메시지를 포함하여 다른 메시지를 수신하지 않고 처리하지 않으므로 응용 프로그램에서 " 사용자 관점에서 "중단"합니다.

짧은 이야기 : 매우 짧은 시간 (최대 수백 밀리 초) 동안 잠을 잘 때까지 잠을 자지 마십시오. 그렇지 않으면 GUI가 응답하지 않게됩니다. 수면을으로 바꿀 수있는 몇 가지 옵션이 있습니다. 타이머 (QTimer)를 사용할 수는 있지만 타이머 이벤트와 다른 이벤트 사이에 많은 부기가 필요할 수 있습니다. 보편적 인 대안은 분리 된 작업자 스레드를 시작하는 것입니다 : 그것은 UDP 통신을 처리 할 뿐이며, 주 스레드와 분리되어 필요에 따라 아무런 문제가 발생하지 않을 것입니다. 당연히 mutex로 스레드간에 공유되는 데이터를 보호하고 멀티 스레딩에서 발생하는 경쟁 조건 및 기타 모든 종류의 문제를 방지하도록주의해야합니다.

+0

직장을 떠날 수 있지만 나중에 오늘 반드시 읽어야합니다;) –

9

가 나는 이벤트 기반 시스템에서 잠을하지 않는 것이 좋습니다하지만 ...
당신은 waitcondition를 사용하려는 경우 neccesary 경우, 그 방법은 항상 수면을 방해 할 수 있습니다.

//... 
QMutex dummy; 
dummy.lock(); 
QWaitCondition waitCondition; 
waitCondition.wait(&dummy, waitTime); 
//... 
관련 문제