如何限制逻辑调用上下文的范围

时间:2010-11-10 17:58:56

标签: .net multithreading

我在调用上下文(CallContext.SetData(key,data))上放置了一些数据,其中数据是实现ILogicalThreadAffinative的类型。它实现ILogicalThreadAffinative的原因是它必须在当前应用程序中的多个线程之间共享。

但是,该应用程序还会远程调用另一个服务,这就是问题所在。我的ILogicalThreadAffinative实现不可序列化,不应该。即使我将其标记为可序列化,远程应用程序也无法访问声明类型的程序集,因此无法对其进行反序列化。

那么如何在我的应用程序(AppDomain)中共享呼叫上下文数据,而不是与它碰巧需要与之交谈的每个外部应用程序共享?

2 个答案:

答案 0 :(得分:6)

最终,我通过实现一个自定义IMessageSink解决了这个问题,我在插入远程调用的客户端格式化器之前插入了该IMessageSink。接收器在通过线路之前剥离呼叫上下文数据。以下是相关方法。

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

我不是特别喜欢这个解决方案。它看起来不仅仅是一点点hackish,但它是我能够提出的最好的解决方案。

答案 1 :(得分:3)

我的理解可能是错误的,将数据放入CallContext就足以使其流经多个线程。只有当您希望它在AppDomains中“自动”流动时,才需要实现ILogicalThreadAffinative(或通过LogicalSetData将数据放入CallContext)。所以看来如果你把你的数据放在CallContext但没有实现ILogicalThreadAffinative它应该做你想要的(在你的应用程序中流动但不跨越Appdomains)?

以下是我在CallContext和ILogicalThreadAffinative(或LogicalSetData)中找到的一些链接:

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

另一个显然引用上述链接信息的链接: http://dotnetmustard.blogspot.com/2008/08/identifying-differences-between.html

(有关log4net如何使用CallContext的解释,请参阅此链接中的Nicko Cadell的回复):

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

祝你好运!