命名空间:System.Runtime.Remoting.Messaging 类型完全限定名称:System.Runtime.Remoting.Messaging.CallContext CallContext 当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时,可将对象添加到其中。 简而言之,CallContext提供线程(多线程/单线程)代码执行路径中数据传递的能力。 在Web环境下等于System.Web.HttpContext.Current 2 探究CallContext方法 上面介绍了CallContext提供的核心方法,下面我们就来通过实践来理解一下。 类,取而代之的是使用AsyncLocal代替,实现的是CallContext.LogicalGetData 和 CallContext.SetLogicalCallContext。 如果你是将.NET Framework升级为.NET Core,那么你可能需要自己实现一个CallContext类来代替之前的CallContext: public static class CallContext
关于CallContext.LogicalSetData参考下面的例子 iii、逻辑调用上下文数据结构CallContext类,关于它的用法,如下: private static string 方法拿到这个数据:{0}", CallContext.GetData(notShareContextKey) ??" ", CallContext.LogicalGetData(shareContextKey) ?? :{0}", CallContext.GetData(notShareContextKey) ?? }", CallContext.LogicalGetData(shareContextKey) ??
目录 一、ThreadStatic字段或者ThreadLocal<T>对象 二、CallContext 三、支持跨线程传递吗? 在初始化的时候,CallStack会创建一个CallStackContext对象并将其放进CallContext对象并对静态字段_current进行复制。 除使用ThreadStatic字段来传递调用链数据之外,我们还可以使用CallContext。 顾名思义,CallContext是专门为调用链创建的上下文,我们首先利用它来实现基于调用链的数据传递。 也就是,只有.NET Framework才提供针对CallContext的支持,.因为我们有更好的选择,那就是AsyncLocal<T>。
IllogicalCallContext CallContext定义在System.Runtime.Remoting.Messaging.CallContext命名空间下,是类似于方法调用的线程本地存储区的专用集合对象 当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时,可将对象添加到其中。 当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时,可将对象添加到其中。 HttpContext本质上也通过CallContext存储的,不过HttpContext本身是作为IllogicalCallContext的形式保存在CallContext,这也正是为何基于HttpSessionState 四、让CallContext实现跨线程传播 也就是说,如果想让CallContext的数据被自动传递当目标线程,只能将其作为LogicalCallContext。
说到这个问题以前就是有解决方案的,那就是CallContext; CallContext 是类似于方法调用的线程本地存储区的专用集合对象,并提供对每个逻辑执行线程都唯一的数据槽。 当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时,可将对象添加到其中。 当使用ASP.NET的时候,虽然线城池里的线程是复用的,但是CallContext并不在一个线程的多次使用中共享。 因为CallContext是针对逻辑线程的TLS,线程池中被复用的线程是操作系统中的内核对象而不是托管对象。就像数据库连接池中保存的是非托管资源而不是托管资源。 因此,先后执行的两个托管线程可能在底层复用了一个物理线程(内核对象),但并不能共享同一组CallContext数据槽。
最近一直在进行公司内部框架的升级工作,其中一个小的部分就是通过HttpSessionState和CallContext建立一套统一的、可扩展的用于管理上下文信息的框架。 以下内容假定读者已经对CallContext有一个大概的了解,并且明白LogicalCallContext和IllogicalCallContext之间的区别。 this.Value = value; 15: } 16: } 然后通过如下一个TestMethod测试一个以LogicalCallContext的形式保存的上下文(通过调用CallContext (userName.Key, userName); 9: Assert.AreEqual<string>("Foo", ((LogicalContextItem<string>)CallContext.LogicalGetData (userNameContext.Key, userNameContext); 7: var userName = ((LogicalContextItem<string>)CallContext.LogicalGetData
在非Web应用中,我们通过CallContext将context信息存储在TLS(Thread Local Storage)中,当前线程下执行的所有代码都可以访问并设置这些context数据。 Application Context通过CallContext实现,定义很简单: 1: namespace Artech.ContextPropagation 2: { 3: 同时,在lcoal domain, client或者service,context是通过CallContext进行存取的,CallContext也是一个类似于disctionary的结构,也需要为此定义一个 8: } 9: 10: return CallContext.GetData(CallContextKey) as ApplicationContext; 11: } 12: set 13: { 14: CallContext.SetData(CallContextKey, value); 15:
一、通过CallContext实现ApplicationContext 在《通过WCF扩展实现Context信息的传递》一文中,我通过HttpSessionState和CallContext实现了一个ApplicationContext 在这里进行了简化,仅仅实现了基于CallContext的部分。 19: context.TimeZone = TimeZoneInfo.Local; 20: CallContext.SetData 而Current属性返回的是通过CallContext的GetData方法获取,并且Key为类型的全名。 Clear则将整个ApplicationContext对象从CallContext中移除。
System.Web.Services.WebService { [WebMethod] public RpcServiceResult CallMethod(RpcServiceContext callContext ); } // extract arguments information var arguments = callContext.Arguments argsTypes = arguments.Select(t => t.Type).ToArray(); MethodInfo method = type.GetMethod(callContext.MethodName new InvalidOperationException(string.Format("Failed to find method named:{0}, with parameters:{1}", callContext.MethodName RpcWebServiceSoapClient(); var returnValueResponse = CallWebServiceWithRetry(proxy.CallMethod, callContext
在非Web应用中,我们通过CallContext将context信息存储在TLS(Thread Local Storage)中,当前线程下执行的所有代码都可以访问并设置这些context数据。 Application Context通过CallContext实现,定义很简单: 1: namespace Artech.ContextPropagation 2: { 3: 同时,在lcoal domain, client或者service,context是通过CallContext进行存取的,CallContext也是一个类似于disctionary的结构,也需要为此定义一个 8: } 9: 10: return CallContext.GetData(CallContextKey) as ApplicationContext; 11: } 12: set 13: { 14: CallContext.SetData(CallContextKey, value); 15:
* @return */ PipeResult execute(CallContext callContext); /** * 业务回滚(只回滚当前指令 ) * * @param callContext * @return */ PipeResult rollback(CallContext callContext * @return */ PipeResult execute(CallContext callContext){ System.out.println(" * @return */ PipeResult execute(CallContext callContext){ System.out.println(" * @return */ PipeResult execute(CallContext callContext){ System.out.println("
OwinMiddleware next) : base(next) { } public async override Task Invoke(IOwinContext context) { CallContext.LogicalSetData ("owinContext", context); await Next.Invoke(context); CallContext.FreeNamedDataSlot(" factoryMethod: (kernel, model, creationContext) => { IOwinContext owinContext = (IOwinContext) CallContext.LogicalGetData
HttpContext.Current.Application应该用System.Web.HttpContext.Current.Application,后来在网上看到一篇关于System.Runtime.Remoting.Messaging.CallContext 这个类的详细介绍才知道,原来HttpContext.Current是基于System.Runtime.Remoting.Messaging.CallContext这个类,子线程和异步线程都无法访问到主线程在 CallContext中保存的数据。
在非Web应用中,我们通过CallContext将context信息存储在TLS(Thread Local Storage)中,当前线程下执行的所有代码都可以访问并设置这些context数据。 Application Context通过CallContext实现,定义很简单: 1: public class ApplicationContext: Dictionary<string, string , new ApplicationContext()); 22: } 23: return (ApplicationContext)CallContext.GetData (KeyOfApplicationContext); 24: } 25: set 26: { 27: CallContext.SetData 具体来说,根据应用类型的不同,我们分别将当前ApplicationContext存放在SessionState和CallContext中。
standard_ProcessUtility函数中IsTransactionBlock() plpgsql_call_handler函数中fcinfo->context plpgsql_call_handler函数中CallContext ->atomic 【成功】call procedure PROCESS_UTILITY_TOPLEVEL false T_CallContext false 【失败】select function 不走 不走 null null 【失败】事务块内call procedure PROCESS_UTILITY_TOPLEVEL true T_CallContext true 【成功】匿名块内call procedure PROCESS_UTILITY_QUERY_NONATOMIC false T_CallContext false 【失败】事务块内匿名块内call procedure PROCESS_UTILITY_QUERY_NONATOMIC true T_CallContext true 【失败】匿名块内select function 不走 不走 null null *对于function来说,进入plpgsql_call_handler
当前ApplicationContext存入CallContext从而实现了在线程范围内共享的目的。 3个常量分别表示ApplicationContext存储于CallContext的Key,以及置于MessageHeader后对应的名称和命名空间。 (callContextKey) == null) 16: { 17: CallContext.SetData(callContextKey 上面我们定义的ApplicationContext借助于CallContext实现了同一线程内数据的上下文消息的共享。 由于CallContext的实现方式是将数据存储于当前线程的TLS(Thread Local Storage)中,所以它仅仅在客户端或者服务端执行的线程中有效。
opcode mem = NewMemory() // bound memory stack = newstack() // local stack callContext logged { in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, callContext, in.returnData ) logged = true } // execute the operation res, err = operation.execute(&pc, in, callContext logged { in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, callContext, in.returnData logged { in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, callContext, in.returnData
protocol::TProtocol> piprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot, void* callContext oprot->getTransport()->flush(); return true; } return process_fn(iprot, oprot, fname, seqid, callContext oprot->getTransport()->flush(); return true; } (this->*(pfn->second))(seqid, iprot, oprot, callContext ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext = NULL) { //得到上下文调用环境 ctx = eventHandler_->getContext(“FacebookService.getName”, callContext);
nonatomic plpgsql_call_handler nonatomic = fcinfo->context && IsA(fcinfo->context, CallContext castNode(CallContext, fcinfo->context)->atomic; SPI_connect_ext(nonatomic ?
替换System.Runtime.Remoting.Messaging.CallContextiBatis.net针对非web的应用也提供了CallContextSessionStore,通过CallContext 但.net core不再提供CallContext类,因此需要将CallContext替换为AsyncLocal类型的字典集合。Emit动态生成程序集相关改动。