知识大全 EntityFramework用法探索:线程安全实践
Posted 知
篇首语:捐躯赴国难,视死忽如归。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 EntityFramework用法探索:线程安全实践相关的知识,希望对你有一定的参考价值。
EntityFramework用法探索:线程安全实践 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
在前文中 我们通过Unity来注册各种类型和WiringUp
IUnityContainer container = new UnityContainer()
RegisterType(typeof(IRepository<>) typeof(Repository<>) new ContainerControlledLifetimeManager())
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
UnityServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator SetLocatorProvider(() => locator);
ICustomerRepository customerRepository = container Resolve
但选择使用了ContainerControlledLifetimeManager对象生命周期管理器 其将每个对象存储为Singleton 这导致在多线程环境下会产生异常
例如我们尝试在多线程条件下更新Customer表
List
for (int i = ; i < ; i++)
DomainModels Customer modifiedCustomer = Mapper Map
modifiedCustomer Name = modifiedCustomer Name + i;
Task t = Task Factory StartNew(() =>
try
customerRepository UpdateCustomer(modifiedCustomer);
catch (Exception ex)
Console WriteLine( Exception occurred in thread + Thread CurrentThread ManagedThreadId);
Console WriteLine(ex Message);
);
tasks Add(t);
Task WaitAll(tasks ToArray());
>但由于我们仍然需要EntityFramework的Local功能 即在当前线程环境下始终使用当前上下文中的对象 我们可能还无法选择其他Unity对象生命期管理模型
此时 我们考虑一种新的方法 引入线程Scope功能 即在给定线程中 使用同一个UnityContainer来维护对象 这样间接利用的EntityFramework的上下文功能
原理很简单 就是为每个线程生成一个单独的ChildUnityContainer
public class UnityContainerScope : IDisposable
private static ConcurrentDictionary
= new ConcurrentDictionary
protected UnityContainerScope()
ScopeId = Thread CurrentThread ManagedThreadId;
scopeMapping Add(ScopeId true);
public int ScopeId get; private set;
public static int ScopeCount get return scopeMapping Count;
public static UnityContainerScope NewScope()
return new UnityContainerScope();
public static bool InScope(int scopeId)
return scopeMapping ContainsKey(scopeId);
public void Dispose()
UnityContainerDispatcher DisposeContainer();
scopeMapping Remove(ScopeId);
这里同时需要一个UnityContainerDispatcher来负责为线程生成Container容器
public static class UnityContainerDispatcher
private static IUnityContainer parentContainer = null;
private static ConcurrentDictionary
= new ConcurrentDictionary
public static void InjectParentContainer(IUnityContainer unity)
if (unity == null)
throw new ArgumentNullException( unity );
parentContainer = unity;
public static IUnityContainer GetContainer()
int key = Thread CurrentThread ManagedThreadId;
if (!UnityContainerScope InScope(key))
throw new UnityContainerNotInScopeException(
string Format(CultureInfo InvariantCulture
The specified scope id [ ] is not in scope key));
if (!containerMapping ContainsKey(key))
BuildUpContainer(key);
return containerMapping Get(key);
public static void DisposeContainer()
int key = Thread CurrentThread ManagedThreadId;
IUnityContainer container = containerMapping Remove(key);
if (container != null)
container Dispose();
private static void BuildUpContainer(int key)
if (parentContainer == null)
throw new InvalidProgramException( The parent container cannot be null );
IUnityContainer childContainer = parentContainer CreateChildContainer();
containerMapping Add(key childContainer);
在注入的根UnityContainer中 我们通过使用CreateChildContainer方法来获取一个新的Container 同时继承所有根容器的注册配置信息 这要求使用HierarchicalLifetimeManager生命期管理器
此时 我们的代码修改为
IUnityContainer container = new UnityContainer()
RegisterType(typeof(IRepository<>) typeof(Repository<>) new HierarchicalLifetimeManager())
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
UnityContainerDispatcher InjectParentContainer(container);
ICustomerRepository customerRepository = container Resolve
创建多线程测试代码
List
for (int i = ; i < ; i++)
DomainModels Customer modifiedCustomer = Mapper Map
modifiedCustomer Name = modifiedCustomer Name + i;
Task t = Task Factory StartNew(() =>
try
using (UnityContainerScope scope = UnityContainerScope NewScope())
customerRepository UpdateCustomer(modifiedCustomer);
Console WriteLine( Modified + modifiedCustomer Name + in thread + Thread CurrentThread ManagedThreadId);
catch (Exception ex)
Console WriteLine( Exception occurred in thread + Thread CurrentThread ManagedThreadId);
Console WriteLine(ex Message);
);
tasks Add(t);
Task WaitAll(tasks ToArray());
测试结果表明已经可以安全的在多线程条件下工作了
> cha138/Article/program/net/201311/12626相关参考
知识大全 java多线程中synchronized关键字的用法
由于同一进程内的多个线程共享内存空间在Java中就是共享实例当多个线程试图同时修改某个实例的内容时就会造成冲突因此线程必须实现共享互斥使多线程同步 最简单的同步是将一个方法标记为synchron
在语言级支持锁定对象和线程间发信使编写线程安全类变得简单本文使用简单的编程示例来说明开发高效的线程安全类是多么有效而直观 Java编程语言为编写多线程应用程序提供强大的语言支持但是编写有用的没有错
C#多线程中lock的用法 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 经常碰到同时需要对某个
java中原子操作是线程安全的论调经常被提到根据定义原子操作是不会被打断地的操作因此被认为是线程安全的实际上有一些原子操作不一定是线程安全的 这个问题出现的原因是尽量减少在代码中同步关键字同
Java线程安全总结 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 最近想将java基础的一些东
Java理论与实践:描绘线程安全性[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 线程安全
Java理论与实践:描绘线程安全性[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 定义线程
Java容器类的线程安全 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Java容器类的关系图
基于Spring+Ibatis的安全线程实现 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 过去
深入研究Servlet线程安全性问题 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Servle