這是在將 memcached 客戶端 EnyimMemcached 遷移至 .Net Core 遇到的問題。
在 MemcachedClient 的構造函數中創建 socket 連接池時,有一個將主機名解析為 IP 地址的操作,之前調用的是同步的 System.Net.Dns.GetHostEntry() 方法,但在 .NET Core 中只有異步的 System.Net.Dns.GetHostAddressesAsync() 方法,所以被迫改為這樣調用:
var addresses = System.Net.Dns.GetHostAddressesAsync(host).Result;
結果只要使用 EnyimMemcached 的 ASP.NET Core 站點在 Linux 上一運行,多個請求進來,就發生死鎖(deadlock)。從瀏覽器端看,請求發出后,就一直處於等待狀態。
不管改為:
var addresses = GetHostAddressesAsync(host).ConfigureAwait(false).GetAwaiter().GetResult();
還是改為:
var addresses = await Task.Run(async () => { return await System.Net.Dns.GetHostAddressesAsync(host); });
都會發生死鎖。
你也許會說,干脆將上層調用方法都改成異步的,但是最上層是 MemcachedClient 的構造函數,沒法改為異步的。如果真要將創建 socket 連接池的操作改為異步的,需要對 EnyimMemcached 的代碼進行大動作。
目前還是打算直接在同步方法中調用異步方法,所以請教一下大家看有沒有什么法子避開死鎖?