从WCF服务调用异步方法

6
我希望从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;
}

我不想在IService接口或SomeMethod方法中添加async。使用异步方法是一个内部问题,不应该反映在接口中。
我该怎么做?
澄清:
我的问题是在非async方法中使用await。我不想改变服务契约(客户端不一定知道async是什么),也不想将方法拆分为BeginSomeMethodEndSomeMethod。我希望有一个使用await的方法,它在内部使用。

相关链接:https://dev59.com/EWEh5IYBdhLWcg3wRBj5 - noseratio - open to work
1个回答

19
无论服务器使用同步还是异步代码,对客户端来说都没有关系。客户端和服务器之间有一个明确定义的协议(通常是SOAP)分离。SOAP没有异步完成的概念。您可以拥有同步服务器和异步客户端,或者反之亦然。客户端甚至无法检测到服务器是同步还是异步。这是一些实施细节。服务器可能是运行Linux的手表,您仍然无法知道。您使用的IO风格是实现细节,并不影响通过网络传输的字节。因此,请选择您喜欢的内容。客户端仍然可以使用异步IO访问服务器。我不确定为什么人们会感到惊讶。在其他上下文中,这似乎非常直观:您可以拥有异步TCP服务器和同步客户端。我可以使用新的WebClient().DownloadString(url)从实现异步方式的Web服务器同步下载字符串。我甚至无法告诉服务器软件正在运行什么。使用Fiddler查看调用WCF时发送的内容。没有同步或异步调用的概念。在幕后,当您异步调用服务时,WCF客户端库以异步方式使用TCP套接字。当您同步调用时,使用阻塞调用使用TCP套接字。这就是整个区别。WCF生成的客户端可以增加异步方法以及同步方法。在UI中选择“生成异步操作”选项。现在您有两个版本。两者都是完全功能的。以下是如何用实验说服自己:编写同步服务器,并从相同的.NET客户端同步和异步调用它。现在以任何方式异步编写第二个服务器,并使用完全相同的客户端代码来调用它。任务和IAsyncResult不能通过SOAP进行序列化,因此不可能传输任务到客户端。

1
我不认为这回答了 @zmbq 在 评论 中提到的目标: "该方法根据定义是长时间执行的方法。 不希望阻塞的客户端将需要实现自己的异步机制。 我希望在服务器上使用异步,而不考虑客户端(例如,客户端可能在运行 .NET 4,但完全没有异步/等待支持)". 我认为我的答案做到了 :) - noseratio - open to work
3
当一个(异步)服务器完成处理后,它会发送响应。在BeginXXX方法完成后不会发送任何响应,没有一字节的响应。响应是在服务器上的EndXXX方法完成之后发送的。在客户端调用EndSomeMethodStart时,它会在服务器的SomeMethodStart返回时立即返回 不是-它会在响应到达后返回。响应是在服务器完成所有处理后到达的。试试看,可以使用Fiddler观察。 - usr
如果我过于坚持不懈,对不起,那是因为我感觉自己在这里缺少一些基础知识。等我一到笔记本电脑就会尝试它。到目前为止,我的观点很简单:如果WCF服务公开了APM或TAP API,则我可以在服务器和客户端上都拥有非阻塞代码,而异步操作在服务器上正在“飞行”。至少,在每一方上少一个被阻塞的线程。然而,如果WCF服务没有公开APM或TAP API,则不可能实现这一点。这个观点不正确吗?如果是这样,为什么? - noseratio - open to work
@usr,我会在问题本身进行澄清。 - zmbq
3
@usr,我现在已经尝试过了。我学到了一些新东西,我改正了自己的错误,非常感谢。 - noseratio - open to work
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接