2012-04-19 4 views
2

GUI가 아닌 스레드 (QThread)에서 GUI 상호 작용을 사용할 수 없다는 것을 알고 있습니다. 그러나 스레드에서 모델 (QAbstractItemModel)과 상호 작용할 수 있는지, 또는 상호 작용할 수 없는지 여부는 알지 못합니다. 참이면 올바른 방법으로 수행하는 방법은 무엇입니까?QThread에서 QAbstractTableModel의 데이터와 상호 작용을 사용할 수 있습니까?

솔직히 Google과 SO에서 이와 관련한 내용을 검색했으며 제 질문에 관련 답변이없는 것으로 보입니다.

답변

2

"모델과 상호 작용"이란 무엇을 의미합니까? 직접 조작하여 여러 스레드에서 모델에 액세스하려는 경우 모델에 대한 액세스를 직렬화해야합니다. 모델 내에는 너무 많은 메소드가 있기 때문에 모델 내에 뮤텍스를 추가하지 말 것을 제안합니다. 뮤텍스 락커를 잊기가 너무 쉽기 때문에 매우 지루하고 오류가 발생하기 쉽습니다. 대신 모델이 QObject를 상속하므로 이벤트를 받아 들일 수 있습니다.

  1. gui 스레드가 모델에 직접 액세스합니다.
  2. 다른 스레드는 이벤트를 이벤트에 게시하고 응답 이벤트를 수신하여 모델과 상호 작용합니다.
  3. gui 스레드는 다른 모든 액세스와 함께 이러한 이벤트를 순차적으로 처리하므로 동시 액세스에서 모델을 보호합니다.

물론 다른 스레드도 이벤트를 통해 모델로부터 응답을받을 수 있습니다. 두 개의 이벤트 기본 클래스가 있습니다. Request 클래스가 모델에서 요청하는 데 사용되며, 모델에서 회신에 사용하는 Response 이벤트 기본 클래스가 있습니다. 요청 클래스에는 QObject* sender 구성원이 있어야합니다. 그러면 모델이 회신 이벤트를 게시 할 QObject를 알 수 있습니다. 요청과 응답이 일치 할 수 있도록 요청과 응답에 동일한 식별자 (예 : 순차적으로 증가하는 int)를 전달해야합니다.

QThread::run()을 다시 구현하지 않고 QObject 내에서 이벤트를 통해 모델과 상호 작용하는 모든 스레드 코드를 구현해야합니다. QObject을 인스턴스화 한 후에는 별도의 스레드로 이동하기 만하면됩니다. QThread의 기본 구현 인 run()은 이벤트, 신호 또는 타이머가 준비되어있는 경우 QObject를 실행하기 위해 이벤트 루프를 돌립니다. 제로 지속 시간 타이머는 스레드를 영구적으로 사용중인 상태로 유지하는 방법이지만 한 번에 너무 많은 처리를하지 않도록하십시오. 그렇지 않으면 수신 이벤트 처리가 지연됩니다.

또한 신호와 슬롯을 사용할 수 있지만 직접 호출 할 수 없습니다, 당신은 할 수 있습니다 그들에게

  1. connect(),
  2. Qt::QueuedConnectionQMetaObject::invokeMethod를 통해 그들을 호출합니다.
  3. 은 주 스레드 컨텍스트에서 실행되는 펑터 (예 : 람다)를 통해 호출합니다. 그 방법은 this answer을 참조하십시오. 별도의 스레드에 상주 QObjects의 슬롯에 신호를 연결 장면 뒤에

은 QT 간격은 QMetaCallEvent로 마샬링 각각의 신호에 해당 연결을 생성하고 스레드를 마샬링 여기서 QObject를 대상 슬롯 목숨 .