7

试图弄清楚为什么这段代码会挂起。我可以删除测试底部的 3 行中的任何一个,它不会挂起,但所有 3 行一起使它挂起。任何帮助将不胜感激!

[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);
}
4

1 回答 1

11

在我看来,这听起来像是混合Waitawait. 这就是为什么你从不这样做- (切换到“吉尔伯特和沙利文”):嗯,几乎从来没有!

如果有帮助,我怀疑删除子树await中的Wait会修复它 - 这应该是微不足道的,因为可以用微不足道的 pass-thru 替换该树:

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

这里的重点是 SE.Redis 在内部绕过了同步上下文(对于库代码来说是正常的),所以它不应该出现死锁。

但最终:混合Wait并不是await一个好主意。除了死锁之外,这是“异步同步”——一种反模式。

于 2014-12-02T22:22:05.633 回答