2011-02-16 6 views
20

응용 프로그램에있는 Dispatcher의 수와 스레드와의 관련성 또는 스레드로부터 참조되는 방법은 완전히 분명하지 않습니다.WPF의 Dispatcher to Thread 관계

알다시피, WPF 응용 프로그램에는 2 개의 스레드 (입력 용, UI 용)와 1 개의 디스패처 (UI 스레드에 연결됨)가 있습니다. 다른 스레드를 생성하면 "worker thread"라고 부르 자. worker thread에서 Dispatcher.CurrentDispatcher이라고 부르면 디스패처가 나옵니까?

또 다른 경우 : 메인 스레드와 입력 스레드 인 2 개의 스레드가있는 콘솔 응용 프로그램을 가정하십시오. 메인 스레드에, 나는 먼저 입력 스레드를 생성하고 난 Application.Run()

Thread thread = new Thread(new ThreadStart(UserInputThreadFunction)); 
thread.Start(); 
Application.Run(); 

오른쪽 하나 디스패처가있을 것입니다 전화? 입력 스레드에서 Dispatcher.CurrentDispatcher가 주 스레드의 디스패처를 반환합니까? 또는 주 스레드의 디스패처로 인스턴스를 가져 오는 올바른 방법은 무엇입니까?

WPF 응용 프로그램에 둘 이상의 디스패처가있을 수 있습니까? 어쨌든 다른 디스패처를 만드는 것이 합리적일까요?

답변

25

WPF 애플리케이션 2 개 스레드 (입력 한 , UI에 대한 다른)

문이 완전히 정확하지있다. WPF 응용 프로그램에는 모든 UI 상호 작용과 사용자 입력을 처리하는 UI 스레드가 하나만 있습니다. 렌더링을 담당하는 "숨겨진"스레드도 있지만 일반적으로 개발자는 처리하지 않습니다.

Dispatcher/스레드 관계는 일대일입니다. 즉, Dispatcher는 항상 하나의 스레드와 연관되어 하나의 스레드로 실행을 디스패치하는 데 사용될 수 있습니다. Dispatcher.CurrentDispatcher은 현재 스레드의 디스패처를 반환합니다. 즉, 작업 스레드에서 Dispatcher.CurrentDispatcher을 호출하면 해당 작업 스레드에 대한 디스패처를 얻습니다.

디스패처는 요청시 생성되며 Dispatcher.CurrentDispatcher에 액세스하고 현재 스레드와 연결된 디스패처가없는 경우 디스패처가 만들어집니다.

즉, 응용 프로그램의 디스패처 수가 응용 프로그램의 스레드 수보다 작거나 같습니다.

+0

그래서 각 스레드마다 실행 루프가 있습니까? 나는 성능상의 이유로 그걸 상상할 수 없다. – j00hi

+0

Dispatcher는 요청에 따라 생성됩니다. 즉, Dispatcher.CurrentDispatcher를 호출 할 때 Dispatcher가 아직없는 경우 생성됩니다. –

+0

그래서 작업자 스레드에서 Dispatcher.CurrentDispatcher를 호출하고 (작업자 스레드의 디스패처를 만들 때) 해당 작업자 스레드의 이벤트를 구독 할 때 해당 이벤트를 수신하려면 Dispatcher.Run()을 호출해야합니까? ? – j00hi

3

dispatcher은 항상 스레드와 연관되며 스레드는 최대 하나의 디스패처를 동시에 실행할 수 있습니다. 스레드는 디스패처를 가질 필요가 없습니다.

기본적으로 UI에는 Dispatcher가 하나만 있습니다. 때로는 다른 운영자를 보유하는 것이 이치에 맞지 않는 경우도 있습니다. Dispatcher로 호출을 처리하려면 디스패치 스레드를 Dispatcher.Run() 메서드에서 차단해야합니다. 콘솔 입력 스레드와 같은 스레드는 호출을 처리 할 수 ​​없습니다.

+0

방금 ​​다음을 시도해 보았지만 효과가있었습니다. Dispatcher.CurrentDispatcher.Invoke (DispatcherPriority.Send, new WaitCallback (delegate (object state) {Console.WriteLine ("Hello Dispatcher");}),'또는 그렇게하지 않았다면 Dispatcher.Run() 동일한 스레드에서 호출되고 다른 스레드에서 호출 된 경우 작동하지 않기 때문에 작동합니다. – j00hi

+1

현재 스레드가 디스패처를 실행 중이기 때문에 작동합니다. WPF 프레임 워크가이를 자동으로 설정합니다. 위의 코드 스 니펫은 UI 스레드에서 실행되므로 다음과 같은 결과가 발생합니다. UI 스레드가 메서드에서 반환됩니다. 예를 들어 버튼에 대한 이벤트 핸들러 내에서 해당 코드를 실행 한 것일 수 있습니다. 그런 다음 Dispatcher는 Console.WriteLine() 호출을 처리하고 실행하는 호출이 있음을 확인합니다. – vidstige

9

기본적으로 WPF 응용 프로그램에는 Dispatcher가 하나만 있습니다. Dispatcher는 UI 요소와 상호 작용할 수있는 유일한 스레드입니다. 구현을 추상화하므로 UI ​​스레드 즉 Dispatcher에 대해서만 신경 써야합니다.

Application.Current.Dispatcher.Invoke(
    () => { txtBkx.Text = "new"; }); 
:

것은 직접 시각적 상호 작용하려는 경우 작업자 스레드에서, 당신은 UI 스레드로 전환해야합니다 (예를 들어, txtBkx.Text = "new"을 사용하여 텍스트 상자에 텍스트를 설정)

또는 (UI 스레드에서) SynchronizationContext.Current을 사용하고이를 사용하여 다른 스레드의 UI 스레드에서 대리자를 실행할 수 있습니다. Dispatcher.CurrentDispatcher은 항상 설정되지 않을 수도 있습니다. 이제

당신이 실제로 동일한 응용 프로그램에서 다른 WPF 창을 만들고 각 창에 대한 개별 디스패처 수 있습니다 : 보조 노트 당신은 비 UI 스레드에서 모델을 업데이트 할 수 있습니다, MVVM에 기억으로

Thread thread = new Thread(() => 
{ 
    Window1 w = new Window1(); 
    w.Show(); 

    w.Closed += (sender2, e2) => 
    w.Dispatcher.InvokeShutdown(); 

    System.Windows.Threading.Dispatcher.Run(); 
}); 

thread.SetApartmentState(ApartmentState.STA); 
thread.Start(); 

을 WPF가 PropertyChanged 이벤트를 마샬링하므로 비 UI 스레드에서 속성 변경 이벤트를 발생시킵니다. CollectionChanged 키우기는 UI 스레드에 있어야합니다.

+1

이 코드 "Application.Current.Dispatcher ..."는 몇 시간 만 절약 해주었습니다 ... 내가 게시 할 때까지 이것이 작동하지 않는 이유를 알 수 없었습니다. 이제는 응용 프로그램 메인 디스패처를 잡는 대신 별도의 Dispatchers를 만드는 중입니다 ... 감사합니다! –

관련 문제