あなたはあなたの質問にいくつかの質問をしました。私はあなたとは少し違う方法でそれらを分解します。しかし、最初に直接質問に答えさせてください。
私たちは皆、軽量で高品質、そして安価なカメラを求めていますが、言われているように、これらの3つのうち多くても2つしか入手できません。ここでも同じ状況です。効率的で安全で、同期パスと非同期パスの間でコードを共有するソリューションが必要です。あなたはそれらのうちの2つだけを手に入れるでしょう。
それがなぜなのかを詳しく見てみましょう。私たちはこの質問から始めましょう:
私は人々があなたがGetAwaiter().GetResult()
非同期メソッドで使用し、それをあなたの同期メソッドから呼び出すことができると言うのを見ましたか?そのスレッドはすべてのシナリオで安全ですか?
この質問の要点は、「同期パスを非同期バージョンで同期待機させるだけで、同期パスと非同期パスを共有できるか」ということです。
重要なので、この点についてははっきりさせておきます。
あなたはそれらの人々からのアドバイスをとるのを直ちに止めるべきです。
それは非常に悪いアドバイスです。非同期タスクから結果を同期的にフェッチすることは非常に危険ですタスクが正常または異常に完了したという証拠がない限りです。
これが非常に悪いアドバイスである理由は、まあ、このシナリオを検討するためです。芝生を刈り取りたいが、芝刈り機のブレードが壊れている。次のワークフローに従うことにしました。
- Webサイトから新しいブレードを注文してください。これは、待機時間の長い非同期操作です。
- 同期的に待機します。つまり、ブレードが手に入るまでスリープします。。。
- メールボックスを定期的にチェックして、ブレードが届いたかどうかを確認してください。
- ブレードを箱から取り出します。今あなたはそれを手にしています。
- ブレードを芝刈り機に取り付けます。
- 芝を刈る。
何が起こるのですか?操作ので、あなたは永遠に眠るメールをチェックがされるようになりましたメールが到着した後に起こる何かにゲートを。
同期的に任意のタスクを待機する場合、この状況に陥るのは非常に簡単です。そのタスクは、現在待機しているスレッドの将来にスケジュールされた作業を持っている可能性がありますあり、今、あなたがそれを待っているので、その未来は決して到着しません。
非同期待機を行う場合、すべてが正常です。あなたは定期的にメールをチェックし、あなたが待っている間、あなたはサンドイッチを作るか、あなたの税金などをします。あなたはあなたが待っている間仕事をやり続けます。
同期的に待機することはありません。タスクが完了したら、それは不要です。タスクが完了していないが、現在のスレッドから実行されるようにスケジュールされている場合、現在のスレッドが待機する代わりに他の作業を処理している可能性があるため、非効率的です。タスクが完了しておらず、現在のスレッドでスケジュール実行が行われている場合、同期して待機するためにハングしています。タスクが完了したことがすでにわかっている場合を除いて、再び同期的に待機する正当な理由はありません。。
このトピックの詳細については、以下を参照してください。
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
スティーブンは、現実のシナリオを私よりもはるかによく説明しています。
それでは、「別の方向」を考えてみましょう。非同期バージョンを単にワーカースレッドで同期バージョンにするだけでコードを共有できますか?
次の理由から、それはおそらく、実際にはおそらく悪い考えです。
同期操作がレイテンシの高いIO作業の場合、非効率的です。これは本質的にワーカーを雇い、タスクが完了するまでワーカーをスリープさせます。スレッドはめちゃくちゃ高価です。デフォルトで最低100万バイトのアドレス空間を消費し、時間がかかり、オペレーティングシステムのリソースを消費します。無駄な作業をしているスレッドを焼きたくない。
同期操作は、スレッドセーフになるように記述されていない場合があります。
これは、レイテンシの高い作業がプロセッサにバインドされている場合はより合理的な手法ですが、そうである場合は、単にワーカースレッドにハンドオフする必要はありません。タスク並列ライブラリを使用して、できるだけ多くのCPUに並列化したり、キャンセルロジックを使用したりする可能性があります。同期バージョンは、すべて非同期バージョンになっているため、単純にそれをすべて行うことはできません。
参考文献; 再び、スティーブンはそれを非常に明確に説明しています:
Task.Runを使用しない理由:
https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-using.html
Task.Runのより多くの「すべきこと」と「すべきでないこと」のシナリオ:
https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html
それでは何を残しますか?コードを共有するための両方の手法は、デッドロックまたは大きな非効率につながります。私たちが到達する結論は、あなたが選択をしなければならないということです。効率的で正しく、呼び出し元を喜ばせるプログラムが必要ですか、それとも、同期パスと非同期パスの間で少量のコードを複製することによって発生するいくつかのキーストロークを節約したいですか?あなたは両方を得ることはできません、私は恐れています。