0

I am using Async and await with multi threading.

If I use Async and await on single thread it works fine but when I use multiple threads, it breaks with an error that I am trying to access dbcontext with multiple threads.

I know I can't do that. But now I want have scheduler which will schedule access of dbcontext to each thread.

How can I code such kind of scheduler/ mutex or whatever that solves this issue.

User
  • 17
  • 1
  • 6

2 Answers2

3

You can definitely use EF with async/await, but you can't perform two operations at once on the same context.

In terms of performance, it's actually faster to create two contexts which looks to be the reason you're using async/await.

For this example, I'd recommend just creating two separate contexts for each CallToDbOps().

Community
  • 1
  • 1
ermish
  • 1,160
  • 2
  • 13
  • 26
  • I am creating another instance of db context if you look at my code, still getting same error. I am confused now – User Jun 27 '16 at 13:04
  • A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe. – User Jun 27 '16 at 13:07
  • You should add an `await` or `Wait()` to `var v = dbo.GetMutualFund();`. Is there any reason you're using Threads vs using the TPL? Instead of `new Thread()`, I'd take a look at `Task.Run()`. Then your CallToDbOps methods can be properly async as well. – ermish Jun 27 '16 at 14:13
  • It was helpful, but it didn't lead to solve the issue, thanks though – User Jul 15 '16 at 04:48
0

This is not so much of an answer as information to help [User]...

Have a read of this blog also have a read of this article about Entity Framework specifications for its async pattern support

DbContext is not thread-safe

You must never access your DbContext-derived instance from multiple threads simultaneously. This might result on multiple queries being sent concurrently over the same database connection. It will also corrupt the first-level cache that DbContext maintains to offer its Identity Map, change tracking and Unit of Work functionalities.

In a multi-threaded application, you must create and use a separate instance of your DbContext-derived class in each thread.

So if DbContext isn't thread-safe, how can it support the async query features introduced with EF6? Simply by preventing more than one async operation being executed at any given time (as documented in the Entity Framework specifications for its async pattern support). If you attempt to execute multiple actions on the same DbContext instance in parallel, for example by kicking off multiple SELECT queries in parallel via the the DbSet.ToListAsync() method, you will get a NotSupportedException with the following message:

A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

Entity Framework's async features are there to support an asynchronous programming model, not to enable parallelism.

Taken from EF article:

"Thread Safety

While thread safety would make async more useful it is an orthogonal feature. It is unclear that we could ever implement support for it in the most general case, given that EF interacts with a graph composed of user code to maintain state and there aren't easy ways to ensure that this code is also thread safe.

For the moment, EF will detect if the developer attempts to execute two async operations at one time and throw."

Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • Does it mean, I can't use multi threding with EF? Do I need to stop using EF? – User Jun 27 '16 at 12:36
  • How can I use await? I have used await everywhere still it cries that context is being used with multiple threads – User Jun 27 '16 at 12:37
  • The issue with async in EF6+ is that each thread must wait for the others before firing off queries, i.e. they cannot work in parrallel, they must await each other... seems counter productive for a multi threaded app to be waiting on each other but that's how it must be for EF6+ ... Personally I tend to do everything in a unit of work pattern. – Paul Zahra Jun 27 '16 at 12:42
  • May I get to see some code? I am trying to code that wait thing but I am still unable to do it. I have added some code if you can look at it – User Jun 27 '16 at 12:43
  • Sorry I'm super busy, got to put some code live soon... last post to point you in the right direction... EF6 attempts to implement async / await as a basic format... as per vs 2012 ... https://msdn.microsoft.com/en-us/library/hh191443(v=vs.110) Read about await and how it doesn't actually wait but enlists in the executing thread and tags it on the end, then returns to the async call. – Paul Zahra Jun 27 '16 at 12:47
  • I would be tempted to go with what the blog says "In a multi-threaded application, you must create and use a separate instance of your DbContext-derived class in each thread." – Paul Zahra Jun 27 '16 at 12:49
  • Thanks ! I'll go through it, I wish if you weren't busy :( – User Jun 27 '16 at 12:55