【问题标题】:NullReference Exception is thrown while getting a callback channel获取回调通道时抛出 NullReference 异常
【发布时间】:2010-04-08 20:56:46
【问题描述】:

我正在努力与 WCF 的双工合同相处。本文中的一段代码

(http://msdn.microsoft.com/en-us/library/ms731184.aspx)

ICalculatorDuplexCallback 回调 = null; 回调 = OperationContext.Current.GetCallbackChannel();

抛出 NullReferenceException。那么我该如何管理呢?

感谢您的关注!

【问题讨论】:

  • 我遇到了同样的问题。你设法解决了这个问题吗?

标签: wcf callback nullreferenceexception duplex contract


【解决方案1】:

你是否为 ICalculatorDuplex 修饰了界面

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
                 CallbackContract=typeof(ICalculatorDuplexCallback))]

当服务接收到消息时,它会查看消息中的 replyTo 元素以确定回复的位置,我猜如果您缺少回调合同属性,它会导致您收到 NullReferenceException,因为它没有不知道在哪里回复。

【讨论】:

    【解决方案2】:

    我刚刚快速浏览了这个示例。

    我的服务代码是:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using System.Text;
    
    namespace DuplexExample
    {
        // Define a duplex service contract.
    // A duplex contract consists of two interfaces.
    // The primary interface is used to send messages from client to service.
    // The callback interface is used to send messages from service back to client.
    // ICalculatorDuplex allows one to perform multiple operations on a running result.
    // The result is sent back after each operation on the ICalculatorCallback interface.
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
                     CallbackContract=typeof(ICalculatorDuplexCallback))]
    public interface ICalculatorDuplex
    {
        [OperationContract(IsOneWay=true)]
        void Clear();
        [OperationContract(IsOneWay = true)]
        void AddTo(double n);
        [OperationContract(IsOneWay = true)]
        void SubtractFrom(double n);
        [OperationContract(IsOneWay = true)]
        void MultiplyBy(double n);
        [OperationContract(IsOneWay = true)]
        void DivideBy(double n);
    }
    
    // The callback interface is used to send messages from service back to client.
    // The Equals operation will return the current result after each operation.
    // The Equation opertion will return the complete equation after Clear() is called.
    public interface ICalculatorDuplexCallback
    {
        [OperationContract(IsOneWay = true)]
        void Equals(double result);
        [OperationContract(IsOneWay = true)]
        void Equation(string eqn);
    }
    // Service class which implements a duplex service contract.
    // Use an InstanceContextMode of PerSession to store the result
    // An instance of the service will be bound to each duplex session
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class CalculatorService : ICalculatorDuplex
    {
        double result;
        string equation;
        ICalculatorDuplexCallback callback = null;
    
        public CalculatorService()
        {
            result = 0.0D;
            equation = result.ToString();
            callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
        }
    
        public void Clear()
        {
            callback.Equation(equation + " = " + result);
            result = 0.0D;
            equation = result.ToString();
        }
    
        public void AddTo(double n)
        {
            result += n;
            equation += " + " + n;
            callback.Equals(result);
        }
    
        public void SubtractFrom(double n)
        {
            result -= n;
            equation += " - " + n;
            callback.Equals(result);
        }
    
        public void MultiplyBy(double n)
        {
            result *= n;
            equation += " * " + n;
            callback.Equals(result);
        }
    
        public void DivideBy(double n)
        {
            result /= n;
            equation += " / " + n;
            callback.Equals(result);
        }
    
    }
    class Program
    {
        static void Main()
        {
            var host = new ServiceHost(typeof(CalculatorService));
    
            host.Open();
            Console.WriteLine("Service is open");
            Console.ReadLine();
    
        }
    }
    

    }

    我的应用程序配置如下:

    <?xml version="1.0" encoding="utf-8" ?>
    

        <services>
            <service behaviorConfiguration="NewBehavior" name="DuplexExample.CalculatorService">
                <endpoint address="dual" binding="wsDualHttpBinding" bindingConfiguration=""
                    contract="DuplexExample.ICalculatorDuplex" />
                <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
                    contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8081/duplex" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
    

    然后我使用配置文件中的主机地址创建了一个名为 CalculatorService 的服务引用。

    所以我的客户看起来像:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using System.Text;
    using Client.CalculatorService;
    
    
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
              var context = new InstanceContext(new CallbackHandler());
    
                var client = new CalculatorDuplexClient(context);
    
                Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.");
                Console.WriteLine();
    
    
                // Call the AddTo service operation.
                var value = 100.00D;
                client.AddTo(value);
    
                // Call the SubtractFrom service operation.
                value = 50.00D;
                client.SubtractFrom(value);
    
                // Call the MultiplyBy service operation.
                value = 17.65D;
                client.MultiplyBy(value);
    
                // Call the DivideBy service operation.
                value = 2.00D;
                client.DivideBy(value);
    
                // Complete equation
                client.Clear();
    
                Console.ReadLine();
    
                //Closing the client gracefully closes the connection and cleans up resources
                client.Close();
            }
        }
    
    
        // Define class which implements callback interface of duplex contract
        public class CallbackHandler : ICalculatorDuplexCallback
        {
            public void Result(double result)
            {
                Console.WriteLine("Result({0})", result);
            }
    
            public void Equation(string eqn)
            {
                Console.WriteLine("Equation({0})", eqn);
            }
    
    
            #region ICalculatorDuplexCallback Members
    
            public void Equals(double result)
            {
                Console.WriteLine("Equals{0} ",result );
            }
    
            #endregion
        }
    }
    

    【讨论】:

    • 是的,一切看起来都不错,但是您没有从服务器调用任何客户端方法,而这正是问题所在。我需要一个回调通道,并定义一个回调接口的空实例,在进一步的代码中使用它会导致一些问题。
    • 你写了 CalculatorDuplexCallback callback = null;回调 = OperationContext.Current.GetCallbackChannel();你不应该在这个方法中传递回调契约吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 2018-06-14
    • 2013-05-31
    • 2012-02-03
    • 2013-01-22
    • 2015-06-24
    • 2013-05-24
    相关资源
    最近更新 更多