2017-08-09 41 views
0

我有一个非常简单的WCF服务,我需要写一个自定义客户端,具有覆盖CreateChannel,但是当我打电话EndInvokeChannelBase里面执行我得到自定义WCF通道引发的NullReferenceException上ChannelBase.EndInvoke

System.NullReferenceException occurred 
    HResult=0x80004003 
    Message=Object reference not set to an instance of an object. 
    Source=System.ServiceModel 
    StackTrace: 
    at System.ServiceModel.Dispatcher.ProxyOperationRuntime.MapAsyncEndInputs(IMethodCallMessage methodCall, IAsyncResult& result, Object[]& outs) 
    at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result) 
    at Client.TestServiceClient.TestServiceChannel.<SayHello>b__1_0(IAsyncResult result) 
    at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 

我不确定我做错了什么,StackTrace也没有帮助我,谷歌没有发现任何有用的东西。我的解决方案是使用.net 4.6.2,并且调用服务成功(它打印到控制台),但EndInvoke从框架代码中抛出。任何援助将不胜感激。

最小摄制:

namespace Service { 
    using System; 
    using System.ServiceModel; 

    [ServiceContract] 
    public interface ITestService { 
     [OperationContract] 
     void SayHello(); 
    } 

    public class TestService : ITestService { 
     public void SayHello() => Console.WriteLine("Hello"); 
    } 
} 


namespace Host { 
    using System; 
    using System.ServiceModel; 
    using Service; 

    internal static class Program { 
     private static void Main() { 
      var host = new ServiceHost(typeof(TestService)); 
      host.AddServiceEndpoint(typeof(ITestService), new BasicHttpBinding(BasicHttpSecurityMode.None), "http://localhost:13377/"); 
      host.Open(); 
      Console.ReadLine(); 
     } 
    } 
} 

namespace Client { 
    using System; 
    using System.ServiceModel; 
    using System.ServiceModel.Channels; 
    using Service; 

    public class TestServiceClient : ClientBase<ITestService>, ITestService { 
     public TestServiceClient(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress) {} 

     public void SayHello() => Channel.SayHello(); 

     protected override ITestService CreateChannel() => new TestServiceChannel(this); 

     private class TestServiceChannel: ChannelBase<ITestService>, ITestService { 
      public TestServiceChannel(ClientBase<ITestService> client) : base(client) {} 

      public void SayHello() => base.BeginInvoke("SayHello", new object[0], result => base.EndInvoke("SayHello", new object[0], result), null); 
     } 
    } 

    internal static class Program { 
     private static void Main() { 
      var client = new TestServiceClient(new BasicHttpBinding(BasicHttpSecurityMode.None), new EndpointAddress("http://localhost:13377/")); 
      client.SayHello(); 
      Console.ReadLine(); 
     } 
    } 
} 

回答

0

的原因是调用BeginInvoke/EndInvoke如果对服务合同具有Begin.../End...对方法只允许。 WCF在内部分析契约接口,并且如果它看到类似异步的方法(从“开始”开始,具有3个或更多参数等),则它初始化一些内部结构,稍后由EndInvoke(在MapAsyncEndInputs中)使用。

如果你想使用WCF基础设施进行异步调用,那么客户端服务契约接口应该是异步风格的。或者,您需要封装整个通道对象以提供异步操作。

您可以检查this answer(选项#3)以查看它是如何完成基于任务的异步模式的。

相关问题