2010-03-05 5 views
2

내 WPF 응용 프로그램에서 서버와 비동기 적으로 통신합니다. 콜백 따라서 UI 스레드에서 실행되지 않습니다 및 일부 WPF 물건을 (InkPresenter 개체 만들기) 할 필요가 UI 스레드에서 실행되도록합니다. 음, 사실 그것은 STA 아파트 모드의 스레드에서 실행된다는 것입니다. STA 모드를 사용하여 새 스레드를 만들려고했지만 UI 스레드가 InkPresenter에 "다른 스레드에서 소유"한 것처럼 액세스 할 수 없었습니다.WPF UI 스레드를 사용하면 항상 STA 아파트 모드를 보장해야합니다. 맞습니까?

콜백에서 수행하려는 작업은 Dispatcher를 사용하여 STA가 필요한 함수를 호출하는 것입니다. 이 방법이 올바른 접근 방식이라고 생각하십니까? 나는 지금이 일을하지만 여전히 실패하고있다. 콜백 함수에서 다음 함수를 트리거합니다. 이제는 주소 지정된 함수가 UI 스레드에서 실행되도록합니다. 샘플에서 보듯이

private void UpdateAnnotationsForCurrentFrameCollection() 
{ 
    if (Dispatcher.CurrentDispatcher.CheckAccess()) 
    { 
     DoSomethingIncludingInkPresenter(); 
    } 
    else 
    { 
     Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, 
      new Action(DoSomethingIncludingInkPresenter)); 
    } 
} 

private void DoSomethingIncludingInkPresenter() 
{ 
    var inkPresenter = XamlReader.Parse(_someXamlString) as InkPresenter; 
    // Do something with the inkPresenter.. 
} 

나는의 checkAccess()가 이미 UI 스레드에서 실행되지 않는 경우 난 단지 함수를 호출 할 수 있도록 사용합니다. 콜백 함수가이 함수를 호출 할 때 CheckAccess()는 항상 true이지만 Dispatcher.CurrentDispatcher.Thread.ApartmentState은 MTA입니다. 왜? CheckAccess()를 제거하고 항상 Invoke를 시도했지만 ApartmentState가 MTA를 유지하고 InkPresenter를 만들지 못합니다.

아무도 내가 여기서 잘못하고있는 것을 설명 할 수 있습니까? Dispatcher 나 다른 무언가가 있습니까? UI 스레드에서 무언가가 실행되도록하는 것이 올바른 접근 방법입니까?

답변

3

2 가지 요구 사항을 혼동스럽게 생각합니다. WinForms 및 WPF 주 스레드는 STA로 표시되어 COM 호출을 활성화합니다 (컨트롤 내부에서 일어날 수 있음).

문제는 고전적인 "UI가 스레드로부터 안전하지 않습니다."문제 인 것 같으며 UI를 터치하는 부분을 파견하여 해결해야합니다.

그러나 당신이 CurrentDispatche에 있지만 대상의 checkAccess를 호출해서는 안 :
someControl.Dispatcher.CheckAccess

+0

감사! Ehr .. 너를 자세히 설명해 줄까? :-) – stiank81

+0

CheckAccess에 대한 잘못된 발송자입니다. –

+0

감사합니다. 그러나 ViewModel에는 디스패처를 가져올 컨트롤이 없습니다. "UI 스레드를위한 일반 디스패처"같은 것이 있습니까? 어쩌면 대답은 ViewModel에 InkPresenter와 같은 WPF 객체를 놓으면 안된다는 것입니다. 하지만 그럴 수 있니? 그렇다면 올바른 디스패처를 얻으려면 어떻게해야합니까? – stiank81

2

을 나는 문제가 잘못된 Dispatcher를 사용하고 있다고 생각합니다. 내가 사용해 본 검증 된 방법 중 하나는 코드가 실행되는 컨트롤의 Dispatcher를 전달하는 것입니다.

private void SomeMethod(Dispatcher dispatcher) 
{ 
    DoOtherThingsThatCanDoMTA(); 

    dispatcher.Invoke(new Action(()=> 
    { 
    DoSomethingThatRequiresSTA(); 
    })); 
} 

어떻게 든 Dispatcher를 전달할 수없는 경우 속성이나 다른 방법으로이를 노출 할 수 있습니다. 도움이되기를 바랍니다.

+0

고마워요. 이 방법은 종종 효과가있을 수 있지만 올바른 Dispatcher에 액세스 할 수있는 것 같지 않습니다. 다른 접근법을 시도해 보지만, 이것에 대한 귀하의 의견에 감사드립니다. – stiank81

+0

MTA/STA 문제가 아닙니다. –

관련 문제