非同期タスクライブラリは例外を静かに飲み込む必要がありますか?


10

.NET 4.5 Taskが内の例外の処理方法に変更を導入したことを知りました。つまり、それらは静かに抑制されます。

これが行われた理由の公式の推論は、「経験の浅い開発者によりフレンドリーになりたかった」ようです。

.NET 4.5では、タスクは.NET 4でのタスクよりもはるかに目立つようになりました。タスクは、言語でサポートされる新しい非同期機能の一部としてC#およびVisual Basic言語に組み込まれているためです。これは事実上、タスクを経験豊富な開発者のドメインからすべての人の領域に移動します。その結果、例外処理の厳格さに関するトレードオフの新しいセットにもつながります。

ソース

.NETでの決定の多くは、自分が何をしているのかを本当に理解している人たちによって行われたものであり、通常、彼らが決定することの背後には非常に正当な理由があると信じています。しかし、これは私を逃れます。

独自の非同期タスクライブラリを設計している場合、フレームワークの開発者が私が見ていなかったと認識した例外を飲み込むことの利点は何ですか?


4
+1。処理できない例外を伝播しないことは非同期コンテキストを除いて悪い習慣であることを考えると、良い質問です。また、経験の浅い開発者についての議論はかなり下手です、私見。機能しないだけでなく例外もスローしないコードよりも、初心者にとって扱いにくいものは何でしょうか。
Arseni Mourzenko 2013

@MainMaまさに私の考えですが、以前は間違っていました(実際には、それが判明したとき、非常に良いが明白ではない理由があった)ので、私は質問したいと思いました。
Roman Starkov 2013

2
うわー、私がこれを聞いたのは初めてなので、これを投稿してくれてうれしいです。そしてそれは間違いなくPOLAに違反しています。それらの人たちが実際に何をしているのかを本当に知っているというのはあなたの言う通りなので、私はこの推論の背後にある推論に心から興味を持っています...非同期の実装と例外がどのように伝播するかに基づいて、より技術的な理由があるかどうか疑問に思いますビーイングはコルーチン...に渡さ
ジミー・ホッファ

回答:


2

価値があるのは、リンク先のドキュメントで正当な理由としてケースの例示していることです

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

このコードでは、開発者は並行して実行する2つの非同期操作を起動し、新しい待機言語機能を使用してそれぞれを非同期的に待機しています... [C] op1とop2の両方に障害が発生した場合にどうなるかを考えます。op1を待機すると、op1の例外が伝播するため、op2を待機することはありません。その結果、op2の例外は監視されず、プロセスは最終的にクラッシュします。

開発者がタスクに基づいて非同期コードを簡単に記述できるようにするために、.NET 4.5は、監視されない例外のデフォルトの例外動作を変更します。監視されていない例外によってUnobservedTaskExceptionイベントが発生しますが(そうしないと重大な変更になります)、プロセスはデフォルトではクラッシュしません。むしろ、イベントハンドラーが例外を監視するかどうかに関係なく、イベントが発生した後、例外は最終的に食べられてしまいます。

これには納得できません。これは、明確ではあるがトレースが困難なエラー(実際のエラーのかなり後に発生する可能性のある謎のプログラムクラッシュ)の可能性を排除しますが、完全に無音のエラーの可能性に置き換えます-後で同様に問題のトレースが困難になる可能性がありますプログラムでオンにします。それは私には疑わしい選択のようです。

動作は設定可能です-もちろん、開発者の99%はデフォルトの動作を使用するだけで、この問題については考えていません。したがって、彼らがデフォルトとして選択したものは大きな問題です。


しかし、あなたが行うため、通常の例外を取得op1、右?場合は、1人の遺骨が未処理の、それがされます、右、プロセスをダウンさせますか?
Timwi 2013

1
@Timwi、私が理解しているように、op1の例外もの例外もop2プログラムを停止させません。利点は、両方を観察する機会があることです。しかし、そうしないと、両方とも飲み込まれてしまいます。しかし、私は間違っている可能性があります。

あなたが両方を「観察」できるようにすることが非常に重要であると彼らが思うことに本当に驚いています。それらを「観察」したい場合は、それらをキャッチし、タスクの結果を介してその発生を報告します!...推論に同意します、+ 1
Roman Starkov

2

TL; DR- いいえ、例外を静かに無視するだけではいけません


仮定を見てみましょう。

  • あなたの盲信

.NETでの決定の多くは、自分が何をしているのかを本当に理解している人たちによって行われたものであり、通常、彼らが決定することの背後には非常に正当な理由があると信じています。しかし、これは私を逃れます。

確かに、MSには素晴らしい人材がいます。彼らにはまた、無知であり、一貫して悪い決定を下すマネージャーやエグゼクティブが多数います。製品開発を推進する技術に精通した科学者のおとぎ話を信じたいのと同じくらい、現実ははるかに厳しいです。

私のポイントは、あなたの本能が何かが間違っているかもしれないと言った場合、それが間違っている可能性が高い(そして過去の前例)場合です。

  • これは技術的な問題であること

この場合の例外の処理方法は、技術的な決定ではなく、人的要因の決定です。大まかに言うと、例外はエラーです。エラーの表示は、フォーマットが不十分であっても、エンドユーザーに重要な情報を提供します。つまり、問題が発生しました。

エンドユーザーと開発者の間の架空の会話について考えてみましょう。

ユーザー:アプリが壊れています。
Dev:何が壊れていますか?
ユーザー:わからない。ボタンをクリックしても何も起こらない。
Dev:何起こらないとはどういう意味ですか?
ユーザー:見て、クリックして、待って、待って、待って、何も...明らかに壊れています。

私たちの貧しい、幸運なことに架空の開発者は、イベントのチェーンで何がうまくいかなかったかを理解する必要があります。どこにあったの?
イベントハンドラー通知->イベントを処理するルーチン->ハンドラーによってトリガーされるメソッド->非同期呼び出しの開始-> OSIネットワークの7層->物理送信-> OSIネットワークの7層のバックアップ->サービスの受信->サービスによって呼び出されるメソッド-> ...->サービスによって送信された返信を返す-> ....->非同期受信->非同期応答の処理-> ...

そして、私はそこにいくつかの潜在的なエラーパスをつぶしたことに注意してください。


いくつかの根本的な仮定に対処した後、例外を静かに抑制することが悪い考えである理由がより明らかになると思います。例外と関連するエラーメッセージは、何かがうまくいかなかったことをユーザーに示す重要な指標です。メッセージがエンドユーザーにとって意味がない場合でも、埋め込まれた情報は、開発者が何が問題だったかを理解するのに役立ちます。運が良ければ、メッセージは解決策につながることさえあります。

ここでの問題の一部は、誤って処理された例外がアプリケーションをクラッシュさせることだと思います。例外を抑制することにより、アプリケーションはクラッシュしません。非同期のポイントは、データが取得されている間、アプリケーションが機能し続けることを可能にすることなので、これにはある程度の妥当性があります。結果を待っている間も操作を続けることができれば、検索の失敗によってアプリケーションがクラッシュすることはないというのは、論​​理的な拡張ではありません。非同期呼び出しは、アプリケーションを終了するほど重要ではないと暗黙的に宣言されています。

したがって、これは解決策ですが、間違った問題を解決しています。アプリケーションを実行し続けることができるように、例外処理にラッパーを提供するのにそれほどの労力は必要ありません。例外がキャッチされ、エラーメッセージが画面にスローされるか、ログに記録され、アプリケーションは実行を継続できます。例外を抑制することは、エラーを無視することはA-OKになることを意味し、テストは例外がとにかくフィールドにエスケープされないことを確認します。

したがって、私の最終的な評価は、思考をそのアプローチにシフトする準備ができていないときに人々を非同期モデルに押し込むことによって作成された問題を解決しようとする中途半端な試みであるということです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.