2016-06-27 3 views
0

Я использую Async и жду с несколькими потоками.Entity Framework: как предотвратить доступ к dbcontext для нескольких потоков?

Если я использую Async и жду в одном потоке, он отлично работает, но когда я использую несколько потоков, он прерывается с ошибкой, которую я пытаюсь получить в dbcontext с несколькими потоками.

Я знаю, что не могу этого сделать. Но теперь я хочу, чтобы планировщик планировал доступ к dbcontext для каждого потока.

Как я могу кодировать такой планировщик/мьютекс или что-то другое, что решает эту проблему.

+0

Вы получаете доступ к * тому же * 'DbContext' из разных тем? –

+0

можете ли вы прикрепить свой код? возможно, вы забыли добавить 'configureawait (false)' для захвата контекста –

+0

Да, Fedeico Dipuma – User

ответ

0

Это не столько ответ, как информация, чтобы помочь [User] ...

Have a read of this blog также have a read of this article about Entity Framework specifications for its async pattern support

DbContext не поточно-

Вы никогда не должны получить доступ к вашим DbContext-экземпляр из нескольких потоков одновременно. Это может привести к одновременному отправке нескольких запросов по одному и тому же соединению с базой данных. Это также повредит кеш первого уровня, который DbContext поддерживает, чтобы предложить свою карту идентификации, отслеживание изменений и функциональность подразделения работы.

В многопоточном приложении вы должны создать и использовать отдельный экземпляр класса DbContext в каждом потоке.

Так что если DbContext не является потокобезопасным, как он может поддерживать функции асинхронного запроса, введенные с EF6? Просто предотвращая выполнение нескольких операций async в любой момент времени (как описано в спецификациях Entity Framework для поддержки асинхронного шаблона). При попытке выполнить несколько действий на той же DbContext, например, параллельно, например, сбрасывая несколько запросов SELECT, параллельно с помощью метода DbSet.ToListAsync(), вы получите NotSupportedException со следующим сообщением:

Вторая операция началась в этом контексте до завершения предыдущей асинхронной операции. Используйте «ждут», чтобы убедиться, что какие-либо асинхронные операции были выполнены до вызова другого метода в этом контексте. Любые члены экземпляра не гарантируют безопасность потоков.

Асинхронные функции Entity Framework предназначены для поддержки асинхронной модели программирования, а не для обеспечения параллелизма.

Взятые из EF статьи:

"Безопасность Thread

Хотя потокобезопасность бы сделать асинхронную более полезным является ортогональной функцией Неясно, что мы могли когда-либо реализовать его поддержку в самых. в общем случае, учитывая, что EF взаимодействует с графиком, состоящим из кода пользователя для поддержания состояния, и нет простых способов гарантировать, что этот код также является потокобезопасным.

На данный момент EF обнаружит, пытается ли разработчик одновременно выполнять две операции асинхронного и бросить ».

+0

Означает ли это, что я не могу использовать multi threding с EF? Нужно ли мне прекратить использование EF? – User

+0

Как я могу использовать ожидание? Я пользовался ожиданием повсюду, но он кричит, что контекст используется с несколькими потоками. – User

+0

Проблема с async в EF6 + заключается в том, что каждый поток должен ждать других, прежде чем запускать запросы, то есть они не могут работать в parrallel, они должны ждать друг друга. .. Кажется, что счетчик производительности для многопоточного приложения ждет друг друга, но так оно и должно быть для EF6 + ... Лично я стараюсь делать все в единице работы. –

3

Вы можете использовать EF с async/await, но you can't perform two operations at once on the same context.

С точки зрения производительности, it's actually faster to create two contexts, который выглядит так, как вы используете async/await.

В этом примере я бы рекомендовал просто создать два отдельных контекста для каждого CallToDbOps().

+0

Я создаю еще один экземпляр контекста db, если вы посмотрите на мой код, все еще получая такую ​​же ошибку. Я запутался сейчас – User

+0

В этом контексте началась вторая операция перед выполнением предыдущей асинхронной операции. Используйте «ожидание», чтобы убедиться, что какие-либо асинхронные операции были выполнены до вызова другого метода в этом контексте. Любые члены экземпляра не гарантируют безопасность потоков. – User

+0

Вы должны добавить 'await' или' Wait () 'to' var v = dbo.GetMutualFund(); 'Есть ли какая-либо причина, по которой вы используете Threads vs, используя TPL? Вместо' new Thread() ', я бы посмотрел на' Task.Run () '.Тогда ваши методы CallToDbOps могут быть правильно асинхронными. – Ermish