从 WCF 服务调用异步方法

Posted

技术标签:

【中文标题】从 WCF 服务调用异步方法【英文标题】:Calling async methods from a WCF service 【发布时间】:2014-04-30 16:17:07 【问题描述】:

我想,例如:

[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;

我不想将async 添加到IService 接口或SomeMethod 方法中。使用异步方法是一个内部问题,不应反映在接口中。

我该怎么做?

澄清:

我的问题是在非async 方法中使用await。我不希望服务合同发生变化(客户端不一定知道async 是什么),我也不希望将方法拆分为BeginSomeMethodEndSomeMethod。我想要一种使用await 内部的方法。

【问题讨论】:

相关:***.com/q/22623922/1768303 【参考方案1】:

服务器使用的是同步还是异步代码对客户端来说并不重要。客户端和服务器由明确指定的有线协议(通常是 SOAP)分隔。 SOAP 没有异步完成的概念。

您可以拥有一个同步服务器和一个异步客户端,反之亦然。 客户端甚至无法检测服务器是同步还是异步。这是一个实现细节。服务器可能是运行 Linux 的手表,但您仍然无法分辨。

您使用的 IO 样式是一个实现细节,不会影响通过网络传输的字节数。

所以选择你喜欢的。客户端仍然可以使用异步 IO 访问服务器。

我不知道为什么这会让人们如此惊讶。在其他情况下,这似乎非常直观:您可以拥有一个异步 TCP 服务器和一个同步客户端。我可以说new WebClient().DownloadString(url) 并从以异步方式实现的网络服务器同步下载字符串。我什至不知道正在运行什么服务器软件。

在进行 WCF 调用时,使用 Fiddler 查看通过线路传输的内容。没有同步或异步调用的概念。

在后台,当您异步调用服务时,WCF 客户端库以异步方式使用 TCP 套接字。当您同步调用时,TCP 套接字与阻塞调用一起使用。这就是全部区别。

除了同步方法之外,WCF 生成的客户端还可以具有异步方法。在 UI 中选择“生成异步操作”选项。现在你有两个版本。两者功能齐全。

您可以通过以下实验来说服自己:编写一个同步服务器,并从同一个 .NET 客户端同时调用它同步和异步。现在异步编写第二个服务器(以您喜欢的任何样式)并使用完全相同的客户端代码来调用它。

TaskIAsyncResult 无论如何都不能通过 SOAP 序列化,因此不可能将 Task 传输到客户端。

【讨论】:

我不认为这回答了@zmbq 在comment 中指出的目标:“根据定义,该方法是一个长时间执行的方法。不希望阻塞的客户端将需要实现他们自己的异步机制。我希望在服务器中使用异步,而不管客户端如何(例如,客户端可能正在运行 .NET 4,根本不支持异步/等待)。” 我认为我的答案是:) 可以在服务器上使用异步,不管客户端做什么。客户端可以同步调用异步服务器。不需要 Task.Wait 或类似的东西。每个生成的 WCF 客户端都有同步和异步调用的方法。两者都工作正常。 让我这么说吧,如果 API 在服务器上启动异步操作(称为 SomeMethodStart),它如何通知客户端其完成?将有一个客户端代理 BeginSomeMethodStartEndSomeMethodStart 方法,但在客户端调用 EndSomeMethodStart 将在 SomeMethodStart 返回服务器后立即返回,而不是在服务器端异步操作结束时返回。他需要的是正确地向客户端公开服务器端的async操作,并且能够在服务器上使用async/await而不阻塞。该服务需要公开 APM 或 TAP API。 当(异步)服务器完成处理时,它会发送响应。 BeginXXX 方法完成后不会发送任何响应。没有一个字节。 EndXXX 方法在服务器上完成后响应。 calling EndSomeMethodStart on the client will return as soon as SomeMethodStart returns on the server 不 - 它在响应到达时返回。在服务器完成all 处理后响应到达。试试吧。用 Fiddler 观察。 @usr,我已经玩过了。我确实学到了一些新东西,我得到了纠正,非常感谢。

以上是关于从 WCF 服务调用异步方法的主要内容,如果未能解决你的问题,请参考以下文章

如何异步调用我的 WCF 服务?

对 WCF 服务的异步调用不会保留 CurrentCulture

对 WCF 服务的异步调用不会保留 CurrentCulture

WCF 异步方法调用返回响应对象

异步调用 WCF 服务并在新任务中等待它

WCF 仅异步操作