How to limit the scope of a logical call context

I put some data in the call context ( CallContext.SetData(key,data) ), where the data is of type that implements ILogicalThreadAffinative . The reason it implements ILogicalThreadAffinative is because it must be shared across multiple threads in the current application.

However, the application also makes remote calls to another service, and this is where the problem arises. My implementation of ILogicalThreadAffinative is not serializable and should not be. Even if I were marked serializable, the remote application does not have access to the assembly in which the type is declared, so it will not be able to deserialize it.

So, how do I share the call context data in my application (AppDomain), but not with every external application that you need to talk to?

+7
multithreading
source share
2 answers

I eventually solved this by implementing a custom IMessageSink that I inserted in front of the client-side formatting receiver of the remote call. The sink deletes the call context data before it passes through the wire. The following is the appropriate method.

 private static void SanitizeCallContext(IMessage msg) { var callContext = msg.Properties["__CallContext"] as LogicalCallContext; if (callContext == null) return; var sanitizedContext = (LogicalCallContext) callContext.Clone(); var prop = typeof (LogicalCallContext).GetProperty("Datastore", BindingFlags.Instance | BindingFlags.NonPublic); var dataStore = (Hashtable) prop.GetValue(sanitizedContext, null); foreach (var key in dataStore.Keys.Cast<string>().ToArray()) sanitizedContext.FreeNamedDataSlot(key); msg.Properties["__CallContext"] = sanitizedContext; } 

I do not particularly like this solution. It seems more than a little hacked, but it is the best solution I could come up with.

+6
source share

My understanding, which may be wrong, is that putting data in a CallContext is enough to make it go through multiple threads. Implementation of ILogicalThreadAffinative (or placing data in CallContext through LogicalSetData) is required only if you want it to be automatically "translated" through AppDomains. It seems like if you put your data in a CallContext but don’t implement ILogicalThreadAffinative, it should do what you want (thread inside your application, but NOT through Appdomains)?

Here are some links I found regarding CallContext and ILogicalThreadAffinative (or LogicalSetData):

http://social.msdn.microsoft.com/forums/en-US/netfxremoting/thread/aec8dda5-102e-44eb-9a41-0a5d8b8b96e9

Another link that seems to reference the information from the link above: http://dotnetmustard.blogspot.com/2008/08/identifying-differences-between.html

(See Nicko Cadell's comment in this link for an explanation of how log4net uses CallContext):

http://www.l4ndash.com/Log4NetMailArchive%2Ftabid%2F70%2Fforumid%2F1%2Fpostid%2F15288%2Fview%2Ftopic%2FDefault.aspx

Good luck

+3
source share

All Articles