2010-08-20 4 views
1

이 질문은 여러 번 제기되었지만 여기에 나와있는 몇 가지 사항을 읽었 기 때문에 다시 질문하고 싶습니다. .NET CF와 관련이 있습니다.) 그리고 합리적인 특정 접근 방식에 대한 유효성 검사를 요청하고 사용자가 가질 수있는 피드백에 감사드립니다.스레드에서 발생하는 오류를 처리하는 표준 방법

어쨌든 상황은 모든 사람과 매우 비슷합니다. 스레드에서 발생하는 오류를 처리하고 싶습니다. 현재 스레드에서 예외를 throw하고 있기 때문에 현재 코드가 제대로 작동하지만 BeginInvoke 대신 Invoke를 사용하고 있습니다.

"지금 스레드를 만든 다음 Invoke를 호출하면 기능을 호출하지 않는 이유는 무엇입니까?"라는 질문에 대해 궁금 할 것입니다. 문제는 작업이 동기식인지 비동기식인지를 지정하는 매개 변수를 통해 호출자에게 유연성을 부여하려는 것입니다.

테스트로 비동기 작업 모드에서 테스트했으며 의도 한대로 자동으로 실패하고 응용 프로그램이 예외가 작업자 스레드에서 발생하는 시점에 디버거에서 종료됩니다.

나는 기본 스레드에서 예외의 행동에 대한 이해뿐만 아니라 disprove the statement in this question on SO (적어도 지금까지 .NET 3.5가 간다), I는 WPF 응용 프로그램에서 몇 가지 테스트 코드를 쓴 등이 있는지 확인하려면 :

코드가 제거되었습니다.

다른 스레드에서 발생한 주 스레드의 이벤트를 처리 할 때 문제가 없어 보이는 것 같습니다.

위 테스트에 동의했다면 내 질문은 간단합니다. 모든 비즈니스 로직이 try/catch 블록으로 묶인 동기화 및 비동기 동작을 제공하는 내 메소드를 작성하는 것이 허용되는 방법입니다. ? 내부 오류가 스레드 내부에 갇히고 동기화 호출 인 경우 예외를 throw하고 비동기 호출 인 경우 이벤트를 발생 시키십시오. 위의 샘플 코드에서 이벤트를 발생시킨 후에도 예외가 발생합니다. 나는 이것이 왜 나에게 어떤 문제를 일으키는 지, 또는 왜 그런지 확실하지 않다.

Pseudo-pseudocode: 

TestFunc(async); 

private TestFunc(bool async) 
{ 
    try { 
    throw new MyAppException("error occurred."); 
    } catch(MyAppException ex) { 
    async ? RaiseErrorEvent : throw; 
    } 
} 

한스 말했듯이 나는 스레드에서 예외를 던질 경우, 그것은 상관없이 문제가 발생할 것

좋아, UPDATE - 기간. 나는이 사건을 시험해 볼 수 있었고, 예외는 던져졌고 F5를 친다면, 그것은 반복해서 던져지고 결코 실을 끝내지 않을 것이다. 이 특정 동작을 이해하지 못합니다. 디버거를 실행할 때 작동하는 방식일까요? 이것은 메소드가 동기화 또는 비동기라고 불리는 지 확인해야한다는 것을 의미합니다. sync 인 경우 오류가 발생합니다. 비동기 인 경우 이벤트를 발생시킵니다.

아마 더 나은 방법은 클라이언트가 항상 예외를 잡는 대신 이벤트로 오류를 처리하도록하는 것입니다. 누구나이 접근법에 대한 생각을 가지고 있습니까?

답변

1

작업을 비동기식으로 실행하는 경우 가장 일반적인 패턴은 스레드에서 예외를 catch하고 작업 완료를 기다리기 위해 결국 동기화 한 후에 다시 throw하는 것입니다. 예를 들어, IAsyncResult pattern에는 EndX()를 호출하여 완료 될 때까지 차단하는 BeginX(), EndX() 호출 구조가 있습니다. EndX() 호출은 호출자가 처리 방법을 결정할 수 있도록 비동기 작업에서 발생한 예외를 throw해야합니다.

.NET 4.0을 사용하는 경우 Task Parallel Library은 작업을 시작한 클라이언트가 비동기 작업을 처리하는 동안 예외를 캡처하고 심지어 집계하여 포괄적으로 지원하므로 작업 처리 방법을 결정할 수 있습니다.

+0

.NET 4.0의 Task에 대해 읽었으며 흥미로 웠습니다. 불행히도 내년 초까지는 4.0으로 업그레이드하지 않습니다. BeginX, EndX에 대한 귀하의 의견을 이해합니다. 이 방법을 사용하지 않는 이유는 내 GUI가 sync/async 메서드의 소비자가 될 수 있기 때문입니다. GUI에서는 명백한 이유로 비 블로킹이라고 부릅니다. 메서드를 호출하고 해당 메서드가 BeginX 다음에 EndX를 호출하면 본질적으로 차단됩니다. 그래서 BeginX 만 부릅니다. 이 경우에는 콜백을 사용할 수 있지만 대신 스레드가 종료되기 전에 이벤트가 발생하기를 기다리고 있습니다. – Dave

+0

@Dave, IAsyncResult의 일반적인 사용 패턴은 콜백입니다. 콜백 내에서 작업을 종료하고 작업 중에 발생한 예외를 throw하도록 EndX()를 호출해야합니다. EndX()를 호출하지 않고도 BeginX()를 호출하는 것은 일반적으로 사용 오류로 간주되지만이 방법은 종종 준수되지 않습니다. 조언을 주신 덕분에 –

+0

. 나는 그것을 시도 할 것이고 우리는 그것이 어떻게 작동하는지 보게 될 것이다. – Dave

2

이 코드로 무엇을 증명하려고하는지 잘 모르겠습니다. AppDomain.Current.UnhandledException에 대한 예외 처리기를 작성하고 e.ExceptionObject.ToString() 값을 기록하거나 표시하십시오.

실제로 을 처리하려는 경우을 처리하는 경우 완전히 다른 생선 주전자를 튀겨야합니다. 무작위로 실행되고 죽는 코드가 있습니다. 얼마나 멀리 나아 갔는지, 그리고 그 프로그램 상태가 그 스레드에 의해 얼마나 바뀌 었는지 당신은 정말로 알지 못합니다.예외를 처리하려면 프로그램 상태를 복원하고 스레드가 수행 한 모든 작업을 취소해야합니다. "폭탄 테러"이벤트를 처리하기 위해 작성하는 이벤트 핸들러가 무엇이든지 상태를 복원하기 위해 수행해야 할 작업을 추측 할 수는 없지만 스레드에 대해 충분히 알지 못합니다. 그것은 그것이 작동하지 않았다는 것을 알고 있습니다. 상태 복원은 스레드 자체에서 수행해야합니다.

"it bombed"이벤트를 처리하는 것은 그 자체로 어렵습니다. 클라이언트 코드는 메시지 상자를 표시 할 수 없으며 기본 창 뒤에 쉽게 사라집니다. UI를 직접 업데이트하는 것은 허용되지 않습니다. 호출은 UI 스레드에 마샬링되어야합니다. 가장 좋은 방법은 클라이언트 코드에 남겨 두어 통지 방법을 결정하는 것입니다. FileSystemWatcher.SynchronizingObject 속성은 좋은 패턴입니다.

+0

아마도이 코드를 게시해서는 안되며, 스레드의 예외 정보를 배경 정보로 던지기위한 고의적 인 예제를 보여주고있었습니다. 예, 예외를 처리해야합니다. 내가 지금하고있는 일은 내 스레드에서 예외를 잡아 내고 예외를 던지는 Error 이벤트 * 및 *를 발생시키는 것입니다. 이 방법을 사용하면 호출자가 동기화 또는 비동기 여부에 관계없이 오류를 처리 할 수 ​​있습니다. 동시 호출을 원하면 try/catch를 사용합니다. 비동기 적으로 호출하려는 경우 이벤트를 등록/등록 취소합니다. 나는이 접근에 대한 의견을 묻기 만하고있다. 그것은 작동하는 것 같습니다. – Dave

+0

예외를 던집니다는 클라이언트 코드가 그것을 잡을 방법이없는 프로그램을 폭파시킵니다. 이벤트는 스레드에서 발생하기 때문입니다. –

관련 문제