從數據庫中獲取數據後,我將其序列化爲XML。Web Api 2返回數據而不格式化異步
然後,我將該XML作爲字符串寫入Redis緩存實例。
我希望端點檢查數據是否存在於緩存中,並根據結果從緩存中返回數據,或者擊中數據庫,緩存數據然後返回該數據。如果一切順利的香蕉試圖使它異步時
工作同步碼
[HttpGet]
public IHttpActionResult Test(int userId)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
var data = Cache.StringGet("Cart:" + userId);
if (string.IsNullOrEmpty(data))
{
// Grab data from DB and format as XML
Cache.StringSet("Cart:" + userId, data, TimeSpan.FromHours(2));
}
response.Content = new StringContent(data);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
return new ResponseMessageResult(response);
}
:當同步執行
我的代碼工作就好了。
破碎異步代碼 (我包括必要的代碼量最小重現該問題)
[HttpGet]
public async Task<HttpResponseMessage> TestAsync(int userId)
{
var data = await Cache.StringGetAsync("Cart:" + userId);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent("<test>Test</test>");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
return response;
}
注意,在這個上面的例子我還沒有訪問異步加載數據。如果我將等待線註釋掉,事情就會重新開始。它只有在代碼中有await時纔會失敗。
發生的問題是,50%的時間,請求端點只是...失速,永遠不會完成。附上的Fiddler屏幕截圖突出了這個問題。
最後,如果跳過媒體格式和內容協商一個更簡單的方法,我會很樂意改變我的做法了。
我應該補充說,將使用此端點的服務僅支持XML,並且對每個請求進行反序列化和重新串行化都沒有意義。
你有沒有試過'等待Cache.StringGetAsync(「Cart:」+ userId).ConfigureAwait(false)'而不是?這聽起來像你可能正在經歷一個典型的ASP.Net死鎖問題(它的組織方式,它喜歡與異步/等待死鎖)。 – 2014-11-06 03:40:44
在破損的代碼中,你爲什麼要訪問Cache.StringGetAsync,當你在調用Cache.StringGet的工作代碼中時,不是已經是Async的TestAsync調用,現在它將等待調用Cache.StringGet的結果。你會檢查這是否解決了問題 – 2014-11-06 04:12:35
@MrinalKamboj我的印象是,正確的異步/等待設計是爲了使鏈中的每個方法都是異步的,以避免阻塞錯誤。例如。異步控制器調用異步服務調用異步數據庫存儲庫,它使用檢索數據的異步方法。刪除await可以解決問題,但也可以使控制器在HttpContext線程上運行時同步。 Cache.StringGetAsync是對redis實例的遠程調用,如果可能的話應該是異步的。 – Bio2hazard 2014-11-06 04:31:15