7

Trying to figure out why this code hangs. I can remove any one of the 3 lines at the bottom of the test and it won't hang, but all 3 together makes it hang. Any help would be greatly appreciated!

[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);
}
8
  • Why do you use Task.Run and why Wait()? Commented Dec 2, 2014 at 21:12
  • 1
    I think problem in Task.Run(() => AddAsync(db, "test", "1")).Wait();. Here you have deadlock. Commented Dec 2, 2014 at 21:13
  • This is the simplified version of my code. Trying to break it down to be as simplified as possible. I am trying to understand what is going on. Commented Dec 2, 2014 at 21:14
  • Apparently I am running into this issue: github.com/StackExchange/StackExchange.Redis/issues/88 Commented Dec 2, 2014 at 21:41
  • @EricJ.Smith: xUnit has a bad habit of providing a SynchronizationContext for all its test methods. This can cause a number of problems when mixing synchronous and asynchronous code. I suspect you're seeing some combination of problems I describe in two blog posts here and here. Commented Dec 2, 2014 at 21:48

1 Answer 1

13

It sounds to me like a sync-context deadlock from mixing Wait and await. Which is why you never do that - (switching into "Gilbert and Sullivan"): well, hardly ever!

If it helps, I suspect that removing the await in the Wait subtree will fix it - which should be trivial since that tree can be replaced with a trivial pass-thru:

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

The important point here is that SE.Redis bypasses sync-context internally (normal for library code), so it shouldn't have the deadlock.

But ultimately: mixing Wait and await is not a good idea. In addition to deadlocks, this is "sync over async" - an anti-pattern.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.