【问题标题】:Is WCF MessageBuffer.CreateMessage thread safe?WCF MessageBuffer.CreateMessage 线程安全吗?
【发布时间】:2011-06-02 01:59:07
【问题描述】:

http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.messagebuffer(v=vs.85).aspx“这种类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。任何实例成员都不能保证是线程安全的。”

作为一般规则,实例成员似乎没有线程安全保证。

但是,我猜一些实例成员方法是可重入和线程安全的,而另一些则不是。

MessageBuffer.CreateMessage 是一个实例方法。 有没有人确认这个特定的方法是否是可重入的(或者调用者是否需要对方法的调用实施锁定)?

【问题讨论】:

    标签: wcf thread-safety reentrancy


    【解决方案1】:

    我认为在明确指定之前,实例方法总是非线程安全的。您可以通过反射器查看此方法来确认。
    另外,您为什么担心这种方法的线程安全?你的使用场景是什么?

    【讨论】:

    • 我们的服务维护多个 MessageBuffers。这些缓冲区用于频繁地创建消息。我想避免每次 CreateMessage 调用的同步构造开销(当然,除非 CreateMessage 调用不可重入)
    • 围绕创建消息添加同步结构会获得什么。 CreateMessage 不会改变原始对象的状态,那么如果 create message 被调用一次或多次,会有什么不同呢。
    • 如果该方法不是可重入的(如您所想),则需要添加同步结构以确保该方法不会被两个不同的线程同时执行
    【解决方案2】:

    MessageBuffer.CreateMessage 是抽象的,因此询问它是否是线程安全的没有意义。 WCF 中 MessageBuffer 的子类都是内部的,因此它们可能会被更改。正如 Chandermani 所说,您应该假设它不是线程安全的。

    更新:它不是线程安全的。创建的消息可能依赖于其他组件,例如消息体的序列化。如果这些组件不是线程安全的,那么 CreateMessage 调用也不能被认为是线程安全的。

    在下面的示例中,对象的序列化版本是时间相关的(它也可能有一些额外的依赖关系),因此CreateMessage 调用的顺序会影响结果。

    public class StackOverflow_6209650_751090
    {
        [DataContract]
        public class MyDC
        {
            [DataMember]
            public DateTime SerializedTime
            {
                get { return DateTime.Now; }
                set { }
            }
        }
        public static void Test()
        {
            Message message = Message.CreateMessage(MessageVersion.None, "foo", new MyDC());
            var buffer = message.CreateBufferedCopy(int.MaxValue);
            Console.WriteLine(buffer.CreateMessage());
            Console.WriteLine();
            Console.WriteLine(buffer.CreateMessage());
        }
    }
    

    【讨论】:

    • CreateBuffer 方法与我无关。我指的是 Message.CreateBufferedCopy 创建的 MessageBuffer 对象(特别是该对象的 CreateMessage 方法是否可重入)。
    • Message.CreateBufferedCopy 内部调用一个虚拟方法 OnCreateBufferedCopy,这取决于创建的消息的类型。另外,我将用一个例子来编辑我的答案,表明它绝对是不是线程安全的。
    • 感谢 Carlos 的示例,我支持您的评论。但是, DateTime.Now 方法(在您的示例中使用)是线程安全的。正如您所提到的,返回值是时间相关的。但是,这并不意味着 DateTime.Now 不是线程安全的或不可重入的。相反, DateTime.Now 是一种线程安全的方法。无论如何,我正在创建的特定消息不是基于时间的。我正在缓存 MessageBuffer,因为数据(静态 xml)在缓存期间不会更改。我的猜测是 CreateMessage 是可重入的,但需要验证这一点。
    猜你喜欢
    • 2011-06-05
    • 2012-10-12
    • 2020-04-15
    • 2011-07-04
    • 2014-04-26
    • 2012-11-30
    • 2010-12-30
    • 2013-03-12
    • 2021-08-03
    相关资源
    最近更新 更多