2010-06-24 4 views
14

내 가상의 예입니다. 하나의 버튼이있는 매우 간단한 WPF 창이 있습니다. Button.Click 이벤트에는 이와 같이 처리기가 있습니다.예외가 WPF Dispatcher.Invoke에 의해 전파되지 않는 이유는 무엇입니까?

Action doit =() => 
{ 
    Action error =() => { throw new InvalidOperationException("test"); }; 

    try { 
     this.Dispatcher.Invoke(error, DispatcherPriority.Normal); 
    } catch (Exception ex) { 
     System.Diagnostics.Trace.WriteLine(ex); 
     throw; 
    } 
}; 
doit.BeginInvoke(null, null); 

나는 예외가 잡힌하고 Trace.WriteLine 호출에 의해 아래로 기록 될 것이라고 기대. 대신 예외가 발견되지 않고 응용 프로그램이 중단됩니다.

아무도이 일이 일어날 가능성이 있음을 알고 있습니까? Dispatcher.Invoke에 의해 호출 된 대리자가 던진 예외를 잡으려면 어떤 해결 방법을 제안합니까?

업데이트 1 : throw을 예외 처리 코드에 넣었습니다. 나는 예외를 실제로 무시하고 싶지 않다. 내 질문의 요점은 올바르게 처리하는 것입니다. 문제는 예외 처리 코드가 절대로 실행되지 않는다는 것입니다.

이것은 가상의 예입니다. 내 진짜 코드는 그렇게 보이지 않습니다. 또한 호출 할 메서드에서 코드를 변경할 수 없다고 가정합니다.

업데이트 2 :이 비슷한 예를 생각해보십시오. WPF 창 대신 Windows Forms 창이 있습니다. 거의 동일한 처리기가있는 버튼이 있습니다. 유일한 차이점은 호출 코드에 있습니다. 그것은 이렇게 간다.

this.Invoke(error); 

예외 처리 코드가 실행됩니다. 차이점은 무엇입니까?

답변

5

업데이트 : 다른 스레드에서 예외를 관찰하려면 같은하는 Task를 사용 Dispatcher 스레드를 대기 (TaskScheduler.FromCurrentSynchronizationContext를 사용하여), 그것에 기다리고 싶지 :

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
Action doit =() => 
{ 
    var error = Task.Factory.StartNew(
     () => { throw new InvalidOperationException("test"); }, 
     CancellationToken.None, 
     TaskCreationOptions.None, 
     ui); 

    try { 
     error.Wait(); 
    } catch (Exception ex) { 
     System.Diagnostics.Trace.WriteLine(ex); 
    } 
}; 
doit.BeginInvoke(null, null); 

업데이트 됨 (다시) : 목표가 재사용 가능한 구성 요소이므로 Dispatcher 또는에 기반하지 않고 Task 기반 인터페이스 또는 event-based asynchronous pattern과 같은 SynchronizationContext을 기반으로하는 다른 항목으로 이동하는 것이 좋습니다..

Dispatcher- 기반 구성 요소는 WPF/Silverlight에서만 작동합니다. ISynchronizeInvoke 기반 구성 요소는 Windows Forms에서만 작동합니다. SynchronizationContext 기반 구성 요소는 WPF 또는 Windows Forms에서 투명하게 작동하며 ASP.NET, 콘솔 응용 프로그램, Windows 서비스 등을 통해 작동합니다.

이벤트 기반 비동기 패턴은 이전에 작성된 권장 작성 방법입니다 SynchronizationContext- 기반 구성 요소. 여전히 .NET 3.5 시대 코드가 있습니다. 하지만 .NET 4에서 작업 병렬 라이브러리는 훨씬 더 유연하고 깨끗하며 강력합니다. TaskScheduler.FromCurrentSynchronizationContext은 아래에 SynchronizationContext을 사용하며 이러한 종류의 동기화가 필요한 재사용 가능한 구성 요소를 작성하는 새로운 방법입니다.

+0

잡힌 예외를 처리하는 방법은 부적합합니다. 나는 로깅을하거나 거기에 무엇이든 넣을 수 있습니다. 문제는 예외 처리 코드가 절대로 실행되지 않는다는 것입니다. – jpbochi

+0

예외가 다른 스레드 인 'Dispatcher'스레드에서 발생하기 때문입니다. –

+1

@Sthepen : 알아. 나는 TargetInvocationException 또는 그와 비슷한 것을 얻을 것으로 예상했다. – jpbochi

관련 문제