2010-11-10 9 views
7

He colocado algunos datos en el contexto de la llamada (CallContext.SetData(key,data)) donde los datos son de un tipo que implementa ILogicalThreadAffinative. La razón por la que implementa ILogicalThreadAffinative es porque debe compartirse entre varios subprocesos en la aplicación actual.Cómo limitar el alcance de un contexto de llamada lógica

Sin embargo, la aplicación también realiza llamadas remotas a otro servicio, y aquí es donde aparece el problema. Mi implementación ILogicalThreadAffinative no se puede serializar y no debería ser. Incluso si tuviera que marcarlo como serializable, la aplicación remota no tiene acceso al ensamblaje en el que se declara el tipo para que no pueda deserializarlo.

Entonces, ¿cómo comparto datos de contexto de llamada dentro de mi aplicación (AppDomain) pero no con cada aplicación externa con la que deba hablar?

Respuesta

6

Al final resolví esto implementando un IMessageSink personalizado que inserté antes del receptor del formateador en el lado del cliente de la llamada remota. El receptor elimina los datos de contexto de llamada antes de que crucen el cable. A continuación está el método relevante.

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; 
    } 

No me gusta especialmente esta solución. Parece más que un poco hackish, pero es la mejor solución que he podido encontrar.

+0

Sé que encontraste una solución a tu problema, pero recientemente encontré este extracto del libro de Jeffrey Richter sobre el uso de ExecutionContext.SuppressFlow para suprimir el flujo de datos de hilos lógicos . No sé si funcionará en el caso que describe, pero, si lo hace, podría ser más limpio que lo que finalmente se le ocurrió: http://blogs.msdn.com/b/microsoft_press/archive/2010 /01/27/jeffrey-richter-excerpt-from-clr-via-c-third-edition.aspx – wageoghe

+0

Wagaoghe, que parece prometedor como una solución alternativa. Me gustaría probarlo en un escenario remoto para estar seguro. Su desventaja es que debe configurarse por llamada dentro del código de llamada.La solución anterior está más orientada a los aspectos y, de alguna manera, más limpia. –

3

Según tengo entendido, lo que podría estar mal es que poner datos en el CallContext es suficiente para hacer que fluya a través de varios hilos. Implementar ILogicalThreadAffinative (o poner los datos en CallContext a través de LogicalSetData) solo es necesario si desea que fluya "automáticamente" en AppDomains. Entonces, parece que si coloca sus datos en CallContext pero no implementa ILogicalThreadAffinative, debe hacer lo que quiera (fluir dentro de su aplicación pero NO a través de Appdomains).

Éstos son algunos enlaces que he encontrado en relación con CallContext y ILogicalThreadAffinative (o LogicalSetData):

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

Otro vínculo que al parecer hace referencia a la información desde el enlace anterior: http://dotnetmustard.blogspot.com/2008/08/identifying-differences-between.html

(Ver Nicko La respuesta de Cadell en este enlace para una explicación de cómo log4net usa CallContext):

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

¡Buena suerte!

+0

Wageoghe, gracias por la respuesta. Sin embargo, ninguno de estos aborda el problema. Todas estas discusiones presuponen un único hilo lógico de ejecución, que puede o no cruzar un Dominio de aplicación, y analizar la diferencia en CallContext versus LogicalCallContext en esa luz. Esta situación se relaciona con CallContext vs LogicalCallContext en el escenario de subprocesos múltiples como se describe aquí: http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/logical-call-context-flowing -data-across-threads-appdomains-and-processes.aspx –

Cuestiones relacionadas