2

우리는 자체 사용자 정의 스레드에서 코드를 실행해야하는 라이브러리를 제공합니다. 완료되면이 스레드가 Dispatcher (System.Windows.Threading.Dispatcher)을 통해 콜백 (이벤트 처리기)을 호출하기를 원합니다. 라이브러리 사용자는 Dispatcher를 사용하여 이벤트 처리를 디스패치합니다.모든 WinRT/Windows 코어 스레드에는 Dispatcher가 있습니까?

우리는 항상 CoreApplication.MainView.CoreWindow.Dispatcher으로 발송할 수 있지만 일부 프로그램 (예 : Windows 10 IoT 핵심 앱)은 UI를 제공하지 않으므로 기본 창이 없습니다.

사용자가 System.Windows.Threading.Dispatcher.CurrentDispatcher을 참조하여 스레드의 Dispatcher을 얻을 수 있습니까? 또는 모든 스레드에 Dispatcher가있을 수 있습니까?

편집 : 다음은이 질문의 배경입니다. 다행히 질문을 이해하기 쉽게 만듭니다. https://github.com/getsenic/nuimo-windows/issues/2

+0

UI 스레드에서 이벤트 처리기를 실행 하시겠습니까? 오히려 일부 객체가 백그라운드 (비 UI) 스레드에서 이벤트를 발생시키는 경우가 일반적입니다. 이벤트 핸들러에서 액세스 UI 요소가 필요하면 라이브러리 사용자가 Dispatcher를 사용하여이 이벤트를 처리해야합니다. – RavingDev

+0

WPF 동작은 다소 비현실적이며 문제가 많은 프로그래머가 많습니다. 여기에 대한 많은 질문이 있습니다. WinRT는 실수를 되풀이하지 않았으며 창에서 발송자 만 얻을 수 있습니다. 논리적 인 접근 방식은 윈도우가 디스패치 루프를 가진 스레드에 의해 만들어 졌을 때만 작동 할 수 있습니다. 창이 없다면 더 이상 특정 스레드에서 코드를 실행할 필요가 없습니다. –

+0

UI 스레드에서 이벤트를 발생시키는 방법은 한 가지가 있습니다. 그러나 객체가 UI 스레드에서 생성되거나 초기화되어야합니다. 그것은 당신의 경우입니까?개체가 UI 스레드에서 생성 된 경우에만 작동합니다. – RavingDev

답변

0

또는 모든 스레드에 Dispatcher가있을 수 있습니까?

Dispatcher 스레드는 항상 UI 스레드에 연결됩니다. IoT 헤드리스 모드 앱에는 UI가 없으므로 Dispatcher 스레드가 없습니다.

사용자는 단순히 자신의 스레드의 디스패처

System.Windows.Threading.Dispatcher.CurrentDispatcher은 기존의 .NET 플랫폼에서 지원받을 System.Windows.Threading.Dispatcher.CurrentDispatcher를 참조 할 수 있습니다. 당신이 지적한대로 UWP 대안은 CoreApplication.MainView.CoreWindow.Dispatcher입니다.

헤드리스 (GUI 없음) 모드에서 비동기 콜백을 수행하려는 경우 TPL (Task Parallel Library), ContinueWhenAll ContinueWhenAny API 등을 참조 할 수 있습니다. https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.aspx을 참조하십시오.

+0

친애하는 재키, 귀하의 회신에 감사드립니다. 불행하게도 작업은 라이브러리 사용자에 의해 시작되지 않고 어느 시점에서든 라이브러리에 의해 시작됩니다 (사실 블루투스 장치의 콜백입니다). 비록 내 질문이 사용자가 디스패치되기를 원하는 스레드에 '이벤트 액션'을 보내는 것에 관한 것이므로 Task가 관련 되어도 상관 없습니다. 특히 그것은 여기에이 문제에 관한 : https://github.com/getSenic/nuimo-windows/issues –

+0

@ LarsBlumberg, 당신은 SynchronizationContext.Post 사용을 고려하고 있습니까? 헤드리스 모드에 따라 UI 또는 일부 UI 스레드에 동기화 컨텍스트를 설정할 수 있습니다. – Jackie

+0

멋진데! 헤드리스 앱은 어디에서'SynchronizationContext'를 얻을 수 있습니까? –

1

처음에는 액세스 UI 요소가 필요한지 클라이언트 만 알기 때문에 UI 스레드에서 이벤트 처리기를 실행해야하는지 잘 모르겠습니다.

두 번째로 CoreApplication.MainView 속성을 호출하기 전에 CoreApplication.Views.Count > 0을 확인할 수 있습니다. 현재 테스트 할 장치가 없기 때문에이 기능이 작동하는지 절대 확신 할 수 없습니다.

또한이 문제를 다른 방법으로 해결할 수 있습니다. 개체 생성자에서 스레드를 실행하는 SynchronizationContext를 저장 한 다음 이벤트를 발생시키는 데 사용합니다. 객체가 UI 스레드에서 인스턴스화되면 작동합니다 (대부분의 경우 사실입니다). 그렇게하면 Dispatcher에서 완전히 거부 할 수 있습니다.

public class NotifierExample 
{ 
    private readonly SynchronizationContext _synchronizationContext; 


    public event EventHandler SomethingHappened; 


    public NotifierExample() 
    { 
     _synchronizationContext = SynchronizationContext.Current; 
    } 


    public void Do() 
    { 
     Task.Factory.StartNew(() => 
     { 
      //do something 
      OnSomethingHappened(); 
     }); 
    } 


    private void OnSomethingHappened() 
    { 
     if (_synchronizationContext != null) 
     { 
      _synchronizationContext.Post(o => RaiseSomethingHappened(), null); 
     } 
     else 
     { 
      RaiseSomethingHappened(); 
     } 
    } 

    private void RaiseSomethingHappened() 
    { 
     var somethingHappened = SomethingHappened; 
     somethingHappened?.Invoke(this, EventArgs.Empty); 
    } 
} 
+0

사용자가 UI 스레드에서 핸들러를 실행하도록 강요하지 않습니다. 그러나 라이브러리는 사용자 정의 스레드에서 라이브러리 이벤트가 발생한다는 사실을 추상화해야합니다. 라이브러리 사용자가 UI를 업데이트하기 위해 모든 콜백을 기본 스레드로 동기화해야하는 경우에는 불편합니다 (있는 경우). 'SynchronizationContext' 사용은 멋지게 - 그것을 시도 할 것입니다! –