2017-08-09 19 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)以查看它是如何完成基於任務的異步模式的。

相關問題