我有一个非常简单的WCF服务,我需要编写一个自定义客户端,必须覆盖CreateChannel
,但是当我在EndInvoke
实现中调用ChannelBase
时,我得到< / p>
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也没有帮助我,google没有找到任何有用的东西。我的解决方案是使用.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 :(得分:0)
原因是只有在服务合同具有BeginInvoke
/ EndInvoke
对方法时,才允许调用Begin...
/ End...
对。 WCF在内部分析契约接口,如果它看到看起来像异步的方法(从“开始”开始,有3个或更多参数等),那么它初始化一些内部结构,这些内部结构稍后由EndInvoke
使用(在MapAsyncEndInputs
)。
如果要将WCF基础结构用于异步调用,则客户端服务协定接口应为异步样式。或者,您需要包装整个通道对象以在顶部提供异步操作。
您可以查看this answer(选项#3),了解基于任务的异步模式是如何完成的。