A second operation started on this context before a previous operation completed

Smith
Smith
None
2568 Points
74 Posts

I'm trying to execute long running process by using System.Threading.Tasks and calling it from MVC controller action:

 new Task( () =>
     {
    // long runing process and fetching data using EntityFrameworkCore
     }).Start();

I'm getting following error:

A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.    at 
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()\r\n   at
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()\r\n   at
System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)\r\n   at
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n   at
System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n   at

 

Views: 11669
Total Answered: 4
Total Marked As Answer: 1
Posted On: 19-Apr-2019 04:51

Share:   fb twitter linkedin
Answers
Priya
Priya
Participant
936 Points
28 Posts
         

The exception tells that db context is being used by two threads at the same time; either two threads in the same request, or by two requests. As you mention that you are execute separate thread for long process.

Posted On: 19-Apr-2019 19:36
beginer
beginer
Member
1328 Points
43 Posts
         

This error in some cases maybe caused by following scenario: if we call an async method but did not used await before calling the method. my problem solved by adding await before the method. however the answer might not be related to the mentioned question but it can be help to similar error.

Posted On: 19-Apr-2019 21:12
Brian
Brian
Moderator
2232 Points
14 Posts
         

You can use lock statement to handle concurrency (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement).

lock (x)
{
  // Your code...
}

In your case, I think, as you mentioned that you are calling from controller action so might be second request came before completion of fist one. In this case following code will resolve your problem:

private readonly object lockObject = new object();

new Task( () =>
{
  lock (lockObject)
  {
    // long runing process and fetching data using EntityFrameworkCore
  }
}).Start();

Any other thread will be  blocked from acquiring the lock and waits until the lock is released.

Posted On: 19-Apr-2019 21:31
It was worked for me
 - Smith  30-Apr-2019 08:05
Rashmi
Rashmi
Member
820 Points
17 Posts
         

I am not sure if you are using Dependency Injection to resolve your DbContext in your .net core application. If you are using native IoC from .NET Core (or any other IoC-Container) and you are getting this error, ensure to register your DbContext as Transient as:

services.AddTransient<MyContext>();
//OR
services.AddDbContext<MyContext>(ServiceLifetime.Transient);
//Instead Of
services.AddDbContext<MyContext>();

AddDbContext or AddScoped adds the context as scoped, which may be cause troubles when working with multiple threads.

Also async / await operations can cause this behavior, when using async lambda expressions.

Adding db context as transient also has its drawbacks. You will not be able to make changes to some entity over multiple classes that are using the context because each class will get its own instance of your DbContext.

Posted On: 19-Apr-2019 21:44
 Log In to Chat