2012-07-10 8 views
14

Dispatcher 대기열을 이해하는 데 도움이 필요하다고 생각합니다.Dispatcher 대기열 이해

새 작업이 도착하면 작업 지정자 큐의 시작 부분에 작업이 추가되고 작업 항목을 처리하려고 할 때 작업 항목이 처음부터 제거됩니다.

좀 더 일반적인 용어로 : 작업이 있으면 작업이 큐에 FIFO 방식으로 저장되고 작업이 남아있을 때 처리됩니다.

The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.

을하지만 어디 이러한 맥락에서 루프는 다음과 같습니다

MSDN 설명서 hereloopframe를 참조한다? 내게있어 루프는 무언가를 반복하고 무언가가 끝나면 다시 시작한다.

그리고 frame의 개념은 무엇입니까? MSDN 설명서에 따르면 프레임은 대기열 안에있는 작업 항목의 펀치입니까? 그렇다면 정적 메서드 Disptatcher.PushFrame()을 어떻게 사용해야합니까?

가장 흥미로운 질문은 큐의 현재 상태를 가져올 수있는 방법이 있는지 여부입니다. 특히 큐에있는 항목 수.

이전에 호출 된 메소드 (즉, Dispatcher 대기열에 넣은 메소드)가 실행되어 즉시 대기열에서 제거되거나 다른 시간 동안 마지막으로 처리되는 경우 보유합니까?

알아요,

+1

첫 번째 질문 : 왜? 왜 Dispatcher에 무엇이 필요할까요? 일반적으로 Dispatcher는 단순히 WPF 프로세스의 "메시지 펌프"입니다. 응용 프로그램 코드 (예 : 마우스 동작, 클릭 등)에 대한 WPF UI를 통해 모든 메시지/이벤트/명령을 처리합니다. 응용 프로그램 Run 메서드가 호출되면 PushFrame을 호출하여 해당 루프를 시작합니다. 동일한 스레드에 대해 다른 스레드를 시작할 수 없습니다. Dispatcher는 UI 작업을 처리하기위한 것입니다. –

+2

[스레딩 모델] (http://msdn.microsoft.com/en-us/library/ms741870.aspx)에 대해 읽었습니까? –

+1

이것은 생산자 - 소비자 문제에 대한 표준 솔루션입니다. http://en.wikipedia.org/wiki/Producer-consumer_problem –

답변

22

:-) 그래서 많은 질문은 Dispatcher 주변의 아주 작은 설명서가, 그래서 당신은 내부 동작에 대해 알고 조금 주위를 분해해야합니다.

Dispatcher는 기본적으로 응용 프로그램의 Message Pump에서 작업을 수행하는 항목입니다. 문제의 사람은 windows message loop 위에 있습니다.

따라서 하나의 응용 프로그램 Dispatcher - Application.Current.Dispatcher으로 액세스 할 수있는 전역 디스패처 개체 만있을 수 있습니다. 다른 운영자는 문서

에있어서 현재 실행 스레드 디스패처를 취득 하나 이미 쓰레드와 연관되어 있지 않은 경우에, 새로운 디스패처를 생성하는 Dispatcher.CurrentDispatcher 액세스가 가능하다.

그러나이 새로운 디스패처에서 Run을 호출하면 차단됩니다.

Dispatcher.PushFrame을 수행하면 기본적으로 현재 발송자에게 프레임이 푸시됩니다. DispatcherFrame과 같이 DispatcherObject에서 상속 된 항목의 디스패처는 현재 상태로 설정됩니다. 생성자를 살펴봄으로써이를 검증 할 수 있습니다. 간단한 이벤트 루프를 가진 물론

private Dispatcher _dispatcher; 

protected DispatcherObject() 
{ 
    this._dispatcher = Dispatcher.CurrentDispatcher; 
} 

는 충분하지 않습니다 - 당신이 할 수있는 다른 작업을 강제로 현재 이벤트 루프를 파괴해야하는 경우가 있습니다. 그래서 당신은 DispatcherFrame입니다.이것이 실제로 이벤트 루프를 구성합니다. 당신이 디스패처에 프레임을 누르면 다음과 같은 절차가 진행됩니다

while (frame.Continue) 
     { 
      if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0)) 
      { 
       break; 
      } 
      this.TranslateAndDispatchMessage(ref msg); 
     } 

메시지를 꺼낸 후에는 디스패처의 우선 순위 큐는 평가를 가져옵니다 TranslateAndDispatchMessage입니다.

Dispatcher에서 작업을 실행하는 데 시간이 오래 걸리면 이벤트 루프가 일시적으로 중지되고 신호에 응답하지 않기 때문에 응용 프로그램이 응답을 멈추는 것처럼 보입니다.

Here's an article 프레임을 사용하여 이벤트 루프가 곧 실행되도록하여 UI가 응답하도록합니다.

큐에 액세스하는 경우, 그대로는 Dispatcher 외부에서 큐의 상태를 알 수있는 방법이 없습니다. 이것은 내부 세부 사항이며 노출되지 않는 것이 합리적입니다.

+1

자세한 답변을 주셔서 대단히 감사합니다. (지연에 대해 죄송합니다.) –

+1

@Marc 문제 없습니다. :) – Asti

+6

_ "결과적으로 애플리케이션 당 하나의 Dispatcher 만있을 수 있습니다."_. <= 사실이 아니므로 디스패처 인스턴스는 스레드에 바인딩됩니다. Dispatcher.CurrentDispatcher의 요약을보십시오 : _ "현재 실행중인 스레드에 대한 정보를 가져오고 아직 스레드와 연관되어 있지 않은 경우 새로 작성합니다."_ Dispatcher를 메시지 펌프의 확장으로 상상해보십시오. 대리자 만 메시지 코드를 처리하는 대신 –