14

여기에 제 가상의 예가 있습니다. 하나의 버튼이있는 매우 간단한 WPF 창이 있습니다. Button.Click 이벤트에는 이와 같이 처리기가 있습니다.

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);

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

1 답변


5

업데이트 :다른 스레드에서 예외를 관찰하려면Task,Dispatcher스레드 (usingTaskScheduler.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); 

업데이트 됨 (다시) :목표는 재사용 가능한 구성 요소이므로,Task기반 인터페이스 또는SynchronizationContext~와 같은이벤트 기반 비동기 패턴, 대신에 구성 요소를 기반으로Dispatcher또는ISynchronizeInvoke.

Dispatcher기반 구성 요소는 WPF / Silverlight에서만 작동합니다.ISynchronizeInvoke기반 구성 요소는 Windows Forms에서만 작동합니다.SynchronizationContext기반 구성 요소는 WPF 또는 Windows Forms와 투명하게 작동하며 ASP.NET, 콘솔 응용 프로그램, Windows 서비스 등 (더 많은 작업이 필요함)

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


  • 잡힌 예외를 처리하는 방법은 부적합합니다. 나는 로깅을하거나 거기에 무엇이든 넣을 수 있습니다. 문제는 예외 처리 코드가 절대로 실행되지 않는다는 것입니다. - jpbochi
  • 예외는 다른 스레드에서 발생하기 때문에Dispatcher실. - Stephen Cleary
  • @Sthepen : 나는 그것을 안다. 나는 TargetInvocationException 또는 그와 비슷한 것을 기대하고 있었다. - jpbochi
  • 예외는 자동으로 스레드간에 전파되지 않습니다. .NET 4.0을 사용하는 샘플을 게시했습니다.Task예외를 전파하라. - Stephen Cleary
  • 이 경우 실제로 이동을 권장합니다.Task기반 인터페이스 또는SynchronizationContext~와 같은이벤트 기반 비동기 패턴. 그 이유는SynchronizationContext기반 접근 방식은 WPF 또는 Windows Forms와 투명하게 작동하며, ASP.NET, 콘솔 응용 프로그램, Windows 서비스 등도 사용할 수 있습니다. 따라서 목표가 재사용 가능한 구성 요소 인 경우SynchronizationContext. - Stephen Cleary

연결된 질문


관련된 질문

최근 질문