我知道当你通过调用BeginInvoke()或ThreadPool.QueueUserWorkItem(...)并行运行某个方法时,.NET框架正在捕获包含代码访问安全信息和其他一些东西的ExecutionContext对象.
我想要的是在ExecutionContext中包含我的并行方法所需的一些数据,但也必须在排队任务时捕获.
问题是我并不总是能控制创建此并行任务的代码,所以我必须找到一种方法来存储这些数据,然后再调用这个外部代码.这就是为什么我想到ExecutionContext类.
当我并不总是控制在线程之间分割工作的代码时,有没有办法将某个状态传递给并行任务.
我正在使用MVC 5教程关注Tom Dykstra的Entity Framework 6 Code First入门. 本教程的第4部分介绍了EF6的连接弹性和命令拦截功能.
作为演示命令拦截使用的一种方式,本教程提供了两个示例DbCommandInterceptor实现.One(SchoolInterceptorLogging)与记录器连接以记录执行的每个SQL命令,执行所花费的时间以及是否存在异常.另一个示例(SchoolInterceptorTransientErrors)模拟瞬态DB错误,以便可以测试连接弹性.
虽然本教程没有特别提到同步问题,但我认为因为单个实例DbCommandInterceptor是通过注册的DbInterception.Add(),所以DbContextDbCommandInterceptor必须同步所使用的状态.例如,SchoolInterceptorLogging应该可能同步使用_stopwatch,并且SchoolInterceptorTransientErrors应该同步_counter.
我想过通过ThreadStaticAttribute或使用线程本地存储ThreadLocal<T>.但是,我不确定这是否足够.假设我的应用程序使用DbContext.SaveChangesAsync()异步保存所有更改.同一个线程是否可以处理两个异步保存操作?如果是这样,那么线程本地存储将无法工作.
另一个想法是在调用上下文中存储每个DbContext状态.但是,使用时CallContext,建议只使用不可变类型.(参见Stephen Cleary的博客文章,Implicit Async Context("AsyncLocal").)
第三个想法是使用a ConcurrentDictionary键,其中键是DbCommandInterceptionContext传递给NonQueryExecuting()/ NonQueryExecuted(),ReaderExecuting()/ ReaderExecuted()或ScalarExecuting()/ ScalarExecuted()的对象,值是一个状态对象.但是,我对这种方法有两个问题:
是个 DbCommandInterceptionContext对于每个保存操作,传递给*Executing()/ *Executed()方法对象是否不同?
从设置断点ReaderExecuting()和调用GetHashCode()拦截上下文对象,对于每次重试而言,它似乎是不同的,更不用说保存操作(经过测试的EntityFramework版本6.1.3).
这个 …