Closed ryazanov-dmitry closed 4 years ago
I have improved the concurrency checks in v2.8.0 for async methods using semaphoreSlim. But it seems you are using EFMaterializer.Materializ
and not the MaterializeAsync
one.
How i can force code to use .MaterializeAsync
instead of .Materialize
which is shown in stacktrace?
Materializing using the ToList
method will use the normal synchronous lock, but ToListAsync
will use the async semaphoreSlim.WaitAsync
version. So just use the xyzAsync
methods of EF Core.
Please check my stacktrace, i am using .ToListAsync()
What are the details of these 3 methods? I want to test them.
var q1 = productTypeUseCase.GetAll();
var q2 = applicationDataUseCase.GetAllApplicationTypes();
var q3 = caseTypeUseCase.GetAll();
q1:
public async Task<List<ProductType>> GetAll()
{
return _uwContext.ProductTypes
.Select(x =>
new ProductType
{
Code = x.Code,
Description = x.Description,
RiskCode = x.RiskCode
})
.ToListAsync();
}
q2:
public async Task<List<ApplicationKind>> GetAllApplicationTypes()
{
return _context.ApplicationTypes.ToListAsync();
}
q3:
public async Task<IList<RefData>> GetAll()
{
return await _uwContext.CaseTypes.Select(x=>RefDataMapper.MapRefDataFrom(x)).Cacheable().ToListAsync();
}
Your sample will crash even without Cacheable()
method (I Tested it). Because when q2 (a normal query without any locks) is started, other queries even q1 (another normal query) are not allowed to be started. In EF(6x and Core), you are not allowed to execute multiple queries concurrently using the same context instance (Task.WhenAll = parallel processing = concurrently using the same context instance).
EF Core does not support multiple parallel operations being run on the same context instance. You should always wait for an operation to complete before beginning the next operation.
using concurrent access could affect scalability negatively as it would mean that in order to process a single request you would be spinning of an arbitrary number of different threads. All the threads would compete for resources such as memory with other threads necessary to server other concurrent requests.
EFSecondLevelCache.Core's locking system only applies if all of your 3 queries are using the Cacheable() method.
Please see this https://stackoverflow.com/a/52857510
And also, why MaterializeAsync
didn't call in my case?
Task.WhenAll
with EF (6x and Core), because it will corrupt its internal state (especially its tracking system, which is not thread safe) and this has nothing to do with EFSecondLevelCache.Core.This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related problems.
Summary of the issue
I have multiple EF select queries that run in async manner, bassically with
Task.WhenAll
using single DbContext object.Environment
Example code/Steps to reproduce:
Now, when i add
.Cacheable()
to one of queries