質問: 私はASP.NET Coreと、 `SaveChanges`と`SaveChangesAsync`を持つEF Coreを使用しています。 私の`DbContext`では、データベースに保存する前に、いくつかの監査/ロギングを実行します。 ``` public async Task LogAndAuditAsync() { // do async stuff } public override int SaveChanges { /*await*/ LogAndAuditAsync(); // what do I do here??? return base.SaveChanges(); } public override async Task SaveChangesAsync { await LogAndAuditAsync(); return await base.SaveChanges(); } ``` 問題は、同期`SaveChanges()`です。 私はいつも "非同期に全部ダウン"しますが、ここでは不可能です。私は`LogAndAudit()`と`LogAndAuditAsync()`再設計することができましたが、それはDRYではなく、私に属していない他の大部分のコードを変更する必要があります。 このトピックに関する他にも多くの質問があり、すべてが一般的で複雑で議論がいっぱいです。 *私はこの特定のケースで最も安全なアプローチを知る必要があり*ます。 ですから、 `SaveChanges()`では、デッドロックを起こさずに非同期メソッドを安全かつ同期的に呼び出す方法を教えてください。
回答: sync-over-asyncを行うには多くの方法があり、それぞれには問題があります。しかし**、この特定のユースケースで最も安全な**ものは**何か**を知る必要がありました。 答えは、Stephen Clearyの「Thread Pool Hack」を使うことです。 ``` Task.Run(() => LogAndAuditAsync()).GetAwaiter().GetResult(); ``` その理由は、この方法では、それ以上のデータベース作業しか実行されないためです。オリジナルの同期化コンテキストは必要ありません`DbContext`コアの`DbContext` 、ASP.NET Coreの`HttpContext`アクセスする必要はありません。 したがって、操作をスレッドプールにオフロードし、デッドロックを回避することが最善です。