2014-12-02 110 views
6

試圖找出爲什麼此代碼掛起。我可以刪除測試底部的3條線中的任何一條,它不會掛起,但所有3條線都會掛起。任何幫助將不勝感激!StackExchange.Redis異步調用掛起

[Fact] 
public async Task CanAddValuesInParallel() { 
    var muxer = ConnectionMultiplexer.Connect("localhost"); 
    var db = muxer.GetDatabase(); 

    await AddAsync(db, "test", "1"); 
    await db.KeyDeleteAsync("test"); 

    Task.Run(() => AddAsync(db, "test", "1")).Wait(); 
} 

public async Task<bool> AddAsync(IDatabase db, string key, string value) { 
    return await db.StringSetAsync(key, value, null, When.NotExists); 
} 
+0

爲什麼使用'Task.Run'和爲什麼'Wait()'? – i3arnon 2014-12-02 21:12:56

+0

我認爲問題在Task.Run(()=> AddAsync(db,「test」,「1」))。Wait();'。這裏你有僵局。 – 2014-12-02 21:13:23

+0

這是我的代碼的簡化版本。試圖將其分解爲儘可能簡化。我想了解發生了什麼事。 – 2014-12-02 21:14:47

回答

10

這聽起來好像從混合Waitawait同步上下文僵局。這就是爲什麼你從來沒有做到這一點 - (切換到「吉爾伯特和沙利文」):well, hardly ever!

如果有幫助,我嫌疑,在Wait子樹移除await將修復它 - 這應該是簡單,因爲那棵樹可以替換爲一個簡單的直通:

public Task<bool> AddAsync(IDatabase db, string key, string value) { 
    return db.StringSetAsync(key, value, null, When.NotExists); 
} 

這裏最重要的一點是,SE.Redis繞過同步上下文內部(正常庫代碼),所以它不應該有死鎖。

但最終:混合Waitawait不是一個好主意。除了死鎖之外,這是「異步同步」 - 一種反模式。