How does using await make code thread safe?
Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance. This includes both parallel execution of async queries and any explicit concurrent use from multiple threads. Therefore, always await async calls immediately, or use separate DbContext instances for operations that execute in parallel.
Say 1 db call is in progress and thread 1 is on it. While it's working in it;
Case 1:
Assume I am not using async. A parallel call is made by another thread, hence there will be clash and error.
Case 2:
Assume I use async. A parallel call is made by another thread:
Case 2.a: since we use async, when 1st thread makes the request, and waiting for response, it will release the thread so thread 2 won't clash when making the request. I get this point.
Case 2.b what if both threads really make request at the same time.
Is case 2.b possible and does using async be of any help here?
CodePudding user response:
"always await async calls immediately" means to avoid starting multiple async operations and waiting for them to finish later (as one would do for multiple HTTP requests).
Here is typical example of what one should do for async HTTP calls but invalid for EF operations:
// start operations early so results are there after our CPU intensive code complete
var task1 = dbContext.GetSomething();
var task2 = dbContext.GetMore();
// do something slow here to let both operations to finish
var result1 = await task1;
// even more code
var result2 = await task2;
This code will let both operations to run in parallel thus potentially causing issues with dbContext.
The guidance recommends:
var result1 = await dbContext.GetSomething();
var result2 = await dbContext.GetMore();
// run slow code now sequntially to avoid parallel calls to dbContext.
Indeed if you are careful you can do similar interleaving of calls on DBContext and other operations on unrelated objects - i.e. HTTP call and DBContext call in parallel, or DBContext call and CPU-intensive code to run in parallel with late awiat of EF call.
Note that the guidance can't help much with sharing context between two threads - as with any non-thread-safe object it is your responsibility to prevent simultaneous access to such shared objects.
CodePudding user response:
The thing you're missing is that in the common case of ASP.NET Core, the DbContext is scoped to the HTTP request, and the framework guarantees that there will be only one middleware or controller method running for a request at any one time. So awaiting the async calls is sufficient to prevent parallel DbContext access.
