web-dev-qa-db-ja.com

同期コードと非同期コードを安全に組み合わせる方法は?

私は純粋に同期しているこのライブラリを持っています。それは同期メソッドを公開し、私はそれを使用しているクライアントを持っています。

基礎となる実装を非同期に変更し、それを使用したい人のために非同期メソッドを公開しました。しかし、今では複製されたコードがたくさんあります。非同期コードの方がパフォーマンスが良いようです。既存のクライアントにそれを利用してもらいたいので、コードの繰り返しを排除したいと思います。

同期署名を保持し、非同期実装を呼び出す安全な方法はありますか?

.Resultと.Waitを呼び出すとき、私は特にデッドロックを恐れています。

19
Igor Gatis

私はあなたにこれをしないように強く勧めますこれをしないでください

まず、 非同期メソッドの同期ラッパーを公開する必要がありますか? および 同期の非同期ラッパーを公開する必要がありますメソッド? StephanToubによる。

私がこれをしない主な理由:

  1. Sync over Async-あなたが言ったように、デッドロック。非同期でResultまたはWaitを使用して、コールチェーンの上位または下位で、リスクの高いビジネスになる可能性があります。実行するプラットフォーム(ASP.NET、UI、コンソール)によって、それぞれの動作が少し異なるため(ConfigureAwait(false)を使用している場合でも)、実際には異なります。

  2. Async over Sync-スケーラビリティ。非同期エンドポイントが表示されたら、それは純粋な非同期であると思います。これは、APIのコンシューマーとして、「背後」でスレッドが回転していないことを意味します。ユーザーが同じことを想定している場合、非同期メソッドを呼び出すたびにスレッドプールスレッドが使用されていることを確認すると、スケールアウトしようとしたときにパフォーマンスが大幅に低下する可能性があります。ユーザーが同期メソッドをTask.Runでラップしたい場合は、それをユーザーに任せてその呼び出しを行い、判断を下しますこれがアプリケーションにどのように影響するか

18
Yuval Itzchakov

ボトムアップから始めてみてください。そうしないと、デッドロックが発生します(

コンソールアプリは、適切に処理されない場合のデッドロックの処理方法に関して、WebアプリやUIアプリとは異なる動作をします。 MVCを使用している場合は、非同期タスクActionResultを使用し、asyncとawaitを使用してTask.Run(()=> SYNCCODE)で特定の同期呼び出しをラップします。イベントメソッド(Clickイベントハンドラーなど)でasync/awaitを使用するUIコードでの同様のプロセス。

私は通常、同期呼び出しを非同期バージョンでラップし、それらをタスクとして処理します。それらの同期メソッドが.NETメソッドの非同期バージョンを利用できる場合、私は可能な限り「より深く」なるように努めます。

3
Ryan Peters