none
InstanceContextMode.PerCall的问题 RRS feed

  • 问题

  • 服务程序如下:

    using System.ServiceModel;
    using System.Threading;
    
    namespace Microsoft.ServiceModel.Samples
    {
        // Define a service contract.
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode = SessionMode.Required)]
        public interface ICalculator
        {
            [OperationContract]
            double Add(double n1, double n2);
            [OperationContract]
            double Subtract(double n1, double n2);
            [OperationContract]
            double Multiply(double n1, double n2);
            [OperationContract]
            double Divide(double n1, double n2);
        }
    
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode = SessionMode.Required)]
        public interface ICalculatorInstance : ICalculator
        {
            [OperationContract]
            string GetInstanceContextMode();
    
            [OperationContract]
            int GetInstanceID();
    
            [OperationContract]
            int GetOperationCount();
        }
    
        [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
        public class CalculatorService : ICalculatorInstance
        {
            static object syncObject = new object();
            static int instanceCount;
            int instanceId;
            int operationCount;
    
            public CalculatorService()
            {
                lock (syncObject)
                {
                    // 每生成一个实例,实例计数加 1。
                    instanceCount++;
                    // 实例的 ID 即为当前已创建的实例总数
                    instanceId = instanceCount;
                }
            }
    
            #region ICalculator 成员
    
            // 每调用一个操作,操作的总数加 1。
    
            double ICalculator.Add(double n1, double n2)
            {
                Interlocked.Increment(ref operationCount);
                return n1 + n2;
            }
    
            double ICalculator.Subtract(double n1, double n2)
            {
                Interlocked.Increment(ref operationCount);
                return n1 - n2;
            }
    
            double ICalculator.Multiply(double n1, double n2)
            {
                Interlocked.Increment(ref operationCount);
                return n1 * n2;
            }
    
            double ICalculator.Divide(double n1, double n2)
            {
                Interlocked.Increment(ref operationCount);
                return n1 / n2;
            }
    
            #endregion
    
            #region ICalculatorInstance 成员
    
            string ICalculatorInstance.GetInstanceContextMode()
            {
                // Return the InstanceContextMode of the service
                ServiceHost host = (ServiceHost)OperationContext.Current.Host;
                ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
                return behavior.InstanceContextMode.ToString();
            }
    
            int ICalculatorInstance.GetInstanceID()
            {
                // Return the id for this instance
                return instanceId;
            }
    
            int ICalculatorInstance.GetOperationCount()
            {
                // Return the number of ICalculator operations performed on this instance
                lock (syncObject)
                {
                    return operationCount;
                }
            }
    
            #endregion
        }
    }
    
    客户端程序如下:
    using System;
    
    namespace Microsoft.ServiceModel.Samples
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Create a client
                CalculatorInstanceClient client = new CalculatorInstanceClient();
                string instanceMode = client.GetInstanceContextMode();
                Console.WriteLine("InstanceContextMode : {0}",instanceMode);
                DoCalculations(client);
    
                // Create a client
                CalculatorInstanceClient client2 = new CalculatorInstanceClient();
    
                DoCalculations(client2);
    
                // Closing the client gracefully closes the connection and cleans up resources
                client.Close();
                client2.Close();
    
                Console.Read();
            }
    
            static void DoCalculations(CalculatorInstanceClient client)
            {
                // Call the Add service operation
                double value1 = 100.00D;
                double value2 = 15.99D;
                double result = client.Add(value1, value2);
                Console.WriteLine("Add({0},{1}) = {2}",value1,value2,result);
                Console.Write("InstanceId : {0}",client.GetInstanceID());
                Console.WriteLine(" , OperationCount: {0}",client.GetOperationCount());
    
                // Call the Subtract service operation
                value1 = 145.00D;
                value2 = 76.54D;
                result = client.Subtract(value1, value2);
                Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
                Console.Write("InstanceId : {0}", client.GetInstanceID());
                Console.WriteLine(" , OperationCount: {0}", client.GetOperationCount());
    
                // Call the Multiply service operation.
                value1 = 9.00D;
                value2 = 81.25D;
                result = client.Multiply(value1, value2);
                Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
                Console.Write("InstanceId : {0}", client.GetInstanceID());
                Console.WriteLine(" , OperationCount: {0}", client.GetOperationCount());
    
                // Call the Divide service operation.
                value1 = 22.00D;
                value2 = 7.00D;
                result = client.Divide(value1, value2);
                Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
                Console.Write("InstanceId : {0}", client.GetInstanceID());
                Console.WriteLine(" , OperationCount: {0}", client.GetOperationCount());
            }
        }
    }
    

    结果如下:

    InstanceContextMode : PerCall
    Add(100,15.99) = 115.99
    InstanceId : 3 , OperationCount: 0
    Subtract(145,76.54) = 68.46
    InstanceId : 6 , OperationCount: 0
    Multiply(9,81.25) = 731.25
    InstanceId : 9 , OperationCount: 0
    Divide(22,7) = 3.14285714285714
    InstanceId : 12 , OperationCount: 0
    Add(100,15.99) = 115.99
    InstanceId : 15 , OperationCount: 0
    Subtract(145,76.54) = 68.46
    InstanceId : 18 , OperationCount: 0
    Multiply(9,81.25) = 731.25
    InstanceId : 21 , OperationCount: 0
    Divide(22,7) = 3.14285714285714
    InstanceId : 24 , OperationCount: 0
    我不明白的是为什么InstanceId每次都加3,而不是从1开始按1递增?

    Do My Best
    2009年10月17日 7:27

答案

  • 你在这个代码块里加上打印
    跟踪这被执行了几次
    以及instanceCount的值变化情况
    lock
    (syncObject)
                {
                    // 每生成一个实例,实例计数加 1。
                    instanceCount++;
                    // 实例的 ID 即为当前已创建的实例总数
                    instanceId = instanceCount;
                }

    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月17日 8:43
    版主
  • Xu Lei,

    你好,我将那个程序改成了控制台托管。已经发到了你的邮箱里。请你帮忙看看,为什么会出现这种情况。

    谢谢。


    Do My Best

    好的,我收到了
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月18日 10:15
    版主
  • Hi LiPei,
    你的代码我今天看了,自己也尝试修改,做了测试。
    基本找到原因了。
    1.你的服务上下文模式是单调PerCall。
    这个也就决定了WCF服务实例会再每次调用时进行实例化。
    2.你客户端的每组调用,都是3次。简单理解就是以Add为例,
     // Call the Add service operation
                double value1 = 100.00D;
                double value2 = 15.99D;
                double result = client.Add(value1, value2);//调用了一次操作
                Console.WriteLine("Add({0},{1}) = {2}",value1,value2,result);
                Console.Write("InstanceId : {0}",client.GetInstanceID());//调用第二次操作
                Console.WriteLine(" , OperationCount: {0}",client.GetOperationCount());//调用第三次操作。
    这里在单调模式下,服务会实例化三次,也就是static int instanceCount;这个变量会进行3计数。
    所以也就是每次累计3.其它运算类似。
    3.我尝试了把服务修改为会话服务PerSession,这里在做测试,就不一样了,针对一个Proxy的调用,服务只实例化一次。

    也在邮件回复你了。请查收。

    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月19日 13:13
    版主

全部回复

  • 你在这个代码块里加上打印
    跟踪这被执行了几次
    以及instanceCount的值变化情况
    lock
    (syncObject)
                {
                    // 每生成一个实例,实例计数加 1。
                    instanceCount++;
                    // 实例的 ID 即为当前已创建的实例总数
                    instanceId = instanceCount;
                }

    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月17日 8:43
    版主
  • Xu Lei,

    你好,我将那个程序改成了控制台托管。已经发到了你的邮箱里。请你帮忙看看,为什么会出现这种情况。

    谢谢。


    Do My Best
    2009年10月18日 5:15
  • Xu Lei,

    你好,我将那个程序改成了控制台托管。已经发到了你的邮箱里。请你帮忙看看,为什么会出现这种情况。

    谢谢。


    Do My Best

    好的,我收到了
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月18日 10:15
    版主
  • Hi LiPei,
    你的代码我今天看了,自己也尝试修改,做了测试。
    基本找到原因了。
    1.你的服务上下文模式是单调PerCall。
    这个也就决定了WCF服务实例会再每次调用时进行实例化。
    2.你客户端的每组调用,都是3次。简单理解就是以Add为例,
     // Call the Add service operation
                double value1 = 100.00D;
                double value2 = 15.99D;
                double result = client.Add(value1, value2);//调用了一次操作
                Console.WriteLine("Add({0},{1}) = {2}",value1,value2,result);
                Console.Write("InstanceId : {0}",client.GetInstanceID());//调用第二次操作
                Console.WriteLine(" , OperationCount: {0}",client.GetOperationCount());//调用第三次操作。
    这里在单调模式下,服务会实例化三次,也就是static int instanceCount;这个变量会进行3计数。
    所以也就是每次累计3.其它运算类似。
    3.我尝试了把服务修改为会话服务PerSession,这里在做测试,就不一样了,针对一个Proxy的调用,服务只实例化一次。

    也在邮件回复你了。请查收。

    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月19日 13:13
    版主
  • 恩!是。谢谢你啊!
    Do My Best
    2009年10月19日 14:24
  • 不要客气啊~
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年10月19日 14:44
    版主