비동기 작업 라이브러리가 예외를 조용히 삼켜야합니까?


10

방금 .NET 4.5에서 내부 예외 Task를 처리 하는 방법이 변경되었다는 것을 알게되었습니다 . 즉, 조용히 억제됩니다.

왜 이런 일이 일어 났는지에 대한 공식 추론은 "경험이없는 개발자들에게 더 친숙해지기를 원했습니다":

.NET 4.5에서 Tasks는 언어에서 지원하는 새로운 비동기 기능의 일부로 C # 및 Visual Basic 언어로 구워 졌기 때문에 .NET 4에서보다 훨씬 두드러졌습니다. 이것은 실제로 숙련 된 개발자의 영역에서 작업을 모든 사람의 영역으로 이동시킵니다. 결과적으로 예외 처리와 관련하여 얼마나 엄격한 지에 대한 새로운 트레이드 오프가 발생합니다.

( 소스 )

.NET의 많은 결정은 자신이하는 일을 실제로 알고있는 사람들이 내린 결정임을 신뢰하는 법을 배웠으며, 일반적으로 그들이 결정한 것 뒤에는 매우 좋은 이유가 있습니다. 그러나 이것은 나를 피합니다.

자체 비동기 작업 라이브러리를 디자인하는 경우 Framework 개발자가 보지 못하는 예외를 삼키면 어떤 이점이 있습니까?


4
+1. 좋은 질문은 예외를 전파하지 않으면 처리 할 수 ​​없다는 점을 감안할 때 비동기 컨텍스트를 제외하고 나쁜 습관입니다. 또한 미숙 한 개발자에 대한 논쟁은 상당히 불명확하다 (IMHO). 작동하지 않을뿐만 아니라 예외도 발생시키지 않는 코드보다 초보자에게 더 어색한 것은 무엇입니까?
Arseni Mourzenko

@MainMa 정확히 내 생각이지만, 나는 전에 잘못했다 (실제로 그들이 아주 좋은하지만 명백하지 않은 이유가 있음을 알았을 때).
Roman Starkov

2
와우, 내가 처음 들었 기 때문에 이것을 게시하게되어 기쁩니다. 그리고 그것은 확실히 POLA를 위반 합니다. 당신은 그 사람들이 실제로 그들이하고있는 일을 알고 있다는 것이 옳습니다. 그래서 어떤 추론이 이것 뒤에 있는지 궁금합니다 .Async의 구현과 예외가 어떻게 전파 될지에 대한 기술적 인 이유가 있는지 궁금합니다. 같은 바닥 존재는 .. 코 루틴에 전달
지미 호파

답변:


2

가치가있는 것에 대해, 당신이 링크 한 문서 는 정당화와 같은 사례 보여줍니다.

Task op1 = FooAsync(); 
Task op2 = BarAsync(); 
await op1; 
await op2;

이 코드에서 개발자는 병렬로 실행하기 위해 두 개의 비동기 작업을 시작한 다음 새로운 대기 언어 기능을 사용하여 각각 비동기식으로 대기합니다. op1을 기다리면 op1의 예외가 전파되므로 op2는 기다리지 않습니다. 결과적으로 op2의 예외는 관찰되지 않으며 프로세스는 결국 중단됩니다.

개발자가 작업을 기반으로 비동기 코드를보다 쉽게 ​​작성할 수 있도록 .NET 4.5는 관찰되지 않은 예외에 대한 기본 예외 동작을 변경합니다. 관찰되지 않은 예외로 인해 UnobservedTaskException 이벤트가 계속 발생하지만 (이렇게하지 않으면 변경이 중단 될 수 있음) 기본적으로 프로세스가 중단되지 않습니다. 오히려 이벤트 핸들러가 예외를 준수하는지 여부에 관계없이 이벤트가 발생한 후 예외가 발생합니다.

나는 이것을 확신하지 못한다. 모호하지는 않지만 추적하기 어려운 오류 (실제 오류 이후에 오랫동안 발생할 수있는 신비한 프로그램 충돌)를 제거하지만 완전히 조용한 오류의 가능성으로 대체합니다. 프로그램에서. 그것은 모호한 선택 인 것 같습니다.

동작은 구성 가능하지만 물론 개발자의 99 %가 기본 동작을 사용하려고하지만이 문제에 대해서는 생각하지 않습니다. 그래서 그들이 기본값으로 선택한 것은 큰 문제입니다.


하지만 당신은 에 대한 일반 예외 얻을 op1, 오른쪽? 경우 하나 개 남아가 처리되지 않은, 그것은 것입니다 오른쪽 과정을 가지고?
Timwi

1
@Timwi는 내가 이해하는 것처럼 op1예외도 예외도 op2프로그램을 중단 시키지 않습니다 . 장점은 두 가지를 모두 관찰 할 수 있다는 것입니다. 그러나 그렇지 않으면 둘 다 삼킬 것입니다. 그래도 틀릴 수 있습니다.

나는 그들이 당신을 둘 다 "관찰"하게하는 것이 매우 중요하다는 것을 정말로 놀랐습니다. 당신이 원하는 경우 그들에게, 당신이 그들을 잡아 작업 결과를 통해 자신의 발생을보고 "관찰"... 당신의 추론, +1에 동의!
로마 Starkov

2

TL; DR- 아니요 , 예외를 조용히 무시해서는 안됩니다.


가정을 보자.

  • 맹목적인 믿음

.NET의 많은 결정은 자신이하는 일을 실제로 알고있는 사람들이 내린 결정임을 신뢰하는 법을 배웠으며, 일반적으로 그들이 결정한 것 뒤에는 매우 좋은 이유가 있습니다. 그러나 이것은 나를 피합니다.

MS는 정말 훌륭한 직원을 보유하고 있습니다. 그들은 또한 실마리가없고 지속적으로 나쁜 결정을 내리는 많은 관리자와 임원이 있습니다. 제품 개발을 주도하는 기술에 정통한 과학자의 동화를 믿고 싶다면 현실이 훨씬 더 어둡습니다.

내 요점은, 당신의 본능이 당신에게 무언가 잘못되었다고 말하면 그것이 잘못되었을 가능성이 높다는 것입니다.

  • 이것이 기술적 문제라는 것

이 경우 예외를 처리하는 방법은 기술적 결정이 아니라 인적 요소 결정입니다. 느슨하게 예외는 오류입니다. 형식이 잘못 되었더라도 오류 표시는 최종 사용자에게 중요한 정보를 제공합니다. 즉, 무언가 잘못되었습니다.

최종 사용자와 개발자 간의 이러한 가상 대화를 고려하십시오.

사용자 : 앱이 고장났습니다.
데브 : 무슨 일이야 ?
User : 몰라요, 버튼을 클릭해도 아무 변화가 없습니다.
Dev : 아무 일도 일어나지 않는다는 것은 무슨 뜻 입니까?
사용자 : 봐, 클릭하고 기다렸다가 기다렸다가 기다리면 아무것도 깨지지 않습니다 ... 분명히 깨졌습니다.

우리의 가난하고 불행하게도 가상의 개발자는 이제 일련의 사건에서 무엇이 잘못되었는지 파악해야합니다. 어디 있었지?
이벤트 핸들러 알림-> 이벤트를 처리하는 루틴-> 핸들러에 의해 트리거되는 메소드-> 비동기 호출의 시작-> OSI 네트워킹의 7 개 계층-> 물리적 전송-> OSI 네트워킹의 7 개 계층 백업-> 서비스 수신-> 서비스에서 호출 한 메소드-> ...-> 서비스에서 보낸 응답 리턴-> ....-> 비동기 수신-> 비동기 응답 처리-> ...

그리고 몇 가지 잠재적 인 오류 경로를 살펴 보았습니다.


기본 가정 중 일부를 해결 한 후 예외를 조용히 억제하는 것이 나쁜 생각 인 이유가 더 명확 해 졌다고 생각합니다. 예외 및 관련 오류 메시지는 사용자에게 문제가 있음을 나타내는 주요 지표입니다. 메시지가 최종 사용자에게 무의미하더라도 임베드 된 정보는 개발자에게 무엇이 잘못되었는지 이해하는 데 유용 할 수 있습니다. 운이 좋으면 메시지가 해결책으로 이어질 것입니다.

여기서 문제의 일부는 잘못 처리 된 예외가 응용 프로그램을 중단시키는 것입니다. 예외를 억제하면 응용 프로그램이 중단되지 않습니다. 비동기 시점은 데이터를 검색하는 동안 응용 프로그램이 계속 작동하도록 허용하는 것이기 때문에 이에 대한 일부 유효성이 있습니다. 결과를 기다리는 동안 계속 작동하면 검색 실패로 인해 응용 프로그램이 중단되지 않아야한다고 말하는 것은 논리적 확장이 아닙니다. 비동기 호출은 암시 적으로 응용 프로그램을 종료하기에 중요하지 않은 것으로 선언됩니다.

따라서 솔루션이지만 잘못된 문제를 해결하고 있습니다. 응용 프로그램이 계속 실행될 수 있도록 예외 처리에 래퍼를 제공하는 데 많은 노력을 기울이지 않습니다. 예외가 발생하고 오류 메시지가 화면에 표시되거나 기록되며 응용 프로그램을 계속 실행할 수 있습니다. 예외를 억제하면 오류를 무시하면 A-OK가되고 테스트를 통해 예외가 필드로 빠져 나가지 않는지 테스트 할 수 있습니다.

따라서 최종 평가는 사람들이 생각을 그 접근 방식으로 전환 할 준비가되지 않았을 때 사람들을 비동기식 모델로 밀어 냄으로써 발생하는 문제를 해결하려는 반쯤 구운 시도라는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.