We ran into a bug where we had to validate a list of objects with an async method. The writer of the code wanted to just stuff it into a Linq expression like so:
var invalidObjects = list
.Where(x => _service.IsValidAsync(x).Result)
.ToList();
The validating method looked something like this:
public async Task<bool> IsValidAsync(object @object) {
var validObjects = await _cache.GetAsync<List<object>>("ValidObjectsCacheKey");
return validObjects.Contains(@object);
}
This little solution caused the whole application to hang on the await _cache.GetAsync
line.
The cache is a distributed cache (redis).
After changing the linq to a simple foreach and properly awaiting _service.IsValidAsync
, the code ran deadlock-free and basically in an instant.
I understand on a basic level how async-await
works, but I can't wrap my head around why this happened especially because the list only had one object.
Any suggestion is welcome!
EDIT: The application is running on .net Core 2.2, but the library in which the problem happened is targeting .netstandard 2.0.
System.Threading.SynchronizationContext.Current
returns null at the time of the deadlock
EDIT2: It turns changing the cache provider (but still accessing it via an async method) also resolves the issue, so the bug might actually be in the redis cache client: https://github.com/aspnet/Caching/blob/master/src/Microsoft.Extensions.Caching.StackExchangeRedis/RedisCache.cs