看来我可以在同一个WCF合同接口API的以下三个不同版本之间自由切换,而不会破坏客户端:
[ServiceContract]
interface IService
{
// Either synchronous
// [OperationContract]
// int SomeMethod(int arg);
// Or TAP
[OperationContract]
Task<int> SomeMethodAsync(int arg);
// Or APM
// [OperationContract(AsyncPattern = true)]
// IAsyncResult BeginSomeMethod(int arg, AsyncCallback callback, object state);
// int EndSomeMethod(IAsyncResult ar);
}
Run Code Online (Sandbox Code Playgroud)
现有的测试客户端应用程序无需重新编译或触摸即可继续工作.如果我重新编译服务并将其引用重新导入客户端应用程序,则WSDL定义保持不变,1:1.
我的问题:
我们的想法是将一组同步SomeMethod方法转换为TAP SomeMethodAsync风格的方法,以便async/await在其实现中使用,从而提高WCF服务的可扩展性,而不会破坏现有客户端.
此外,已知在.NET 3.5和.NET 4.0下WCF服务扩展的问题.它们记录在MSKB文章"WCF服务可能在负载下缓慢扩展"和CodeProject文章"调整WCF以构建高度可伸缩的异步REST API"中.基本上,将服务契约API实现为自然异步是不够的,WCF运行时仍然阻塞了请求线程.
当激活以下服务时,我得到以下异常(在相同的合同中不能有两个操作,具有相同的名称,方法ExecuteAsync和Execute).
[ServiceContract]
public interface IMyService
{
[OperationContract]
byte[] Execute(MyRequest request);
[OperationContract]
Task<byte[]> ExecuteAsync(MyRequest request);
}
Run Code Online (Sandbox Code Playgroud)
我想如果您使用svcutil.exe来创建服务引用,这是有道理的,因为基于任务的操作是自动为您创建的.但是,我不想添加服务引用,而只是使用标准ChannelFactory来创建WCF通道.如果不将异步方法重命名为其他方法,还有其他方法吗?或者我必须在Task.Run中将sync方法包装在客户端上吗?
我正在使用WCF和TPL异步库,我需要的是能够请求多个WCF方法并等待所有步骤都完成,到目前为止,我发现.NET 4.5中有非常方便的方法Task.Factory.ContinueWhenAll可以用于等待所有通话结束
我发现了以下几种以异步方式请求WCF调用的方法
。通过使用由“添加引用”对话框生成的代理以及选项“生成基于任务的操作”-> [例如,此处] [1]-在我的情况下不是一个选项就像我们使用Raw ChannelFactory
Option 2一样。通过将同步调用包装在任务中,例如
ChannelFactory<IService1> factory = new ChannelFactory<IService1>("BasicHttpBinding_IService1");
Task<string> t1 = Task<string>.Factory.StartNew(() => { return factory.CreateChannel().GetData(2); });
Task<string> t2 = Task<string>.Factory.StartNew(() => { return factory.CreateChannel().GetData(5); });
Task.Factory.ContinueWhenAll(new[] { t1, t2 }, t =>
{
foreach (var task in t)
{
//get result here
}
});
Run Code Online (Sandbox Code Playgroud)
选项3.通过创建客户端异步版本的契约接口,例如
[ServiceContract(Namespace = "X", Name = "TheContract")]//Server side contract
public interface IService1
{
[OperationContract]
string GetData(int value);
}
[ServiceContract(Namespace = "X", Name = "TheContract")]//client side contract
public …Run Code Online (Sandbox Code Playgroud) 我想从WCF服务调用异步方法,如:
[ServiceContract]
interface IService
{
[OperationContract]
int SomeMethod(int data);
}
int SomeMethod(int data)
{
var query = ... build LINQ query;
var response = await query.ToListAsync();
return response.Length;
}
Run Code Online (Sandbox Code Playgroud)
我不想添加async到IService界面或SomeMethod方法.使用异步方法是一个内部问题,不应该在接口中反映出来.
我怎样才能做到这一点?
澄清:
我的问题是await在非async方法中使用.我不希望服务合同发生变化(客户端不一定知道是什么async),我不想将方法拆分为BeginSomeMethod和EndSomeMethod.我想要一种await 内部使用的方法.
我几乎没有编写程序问题的异步方式.我正在用一些昂贵的方法编写WCF服务,这些方法非常适合异步调用.但我对这些实现的问题是:
Task<originalType>.这将破坏服务API约定的一致性.什么是正确的方法?将服务接口设计为async Task返回方法是否更好,即使某些方法并不昂贵且实际上没有理由使其异步?