使用共享接口跨网络进行异步同步

时间:2015-04-16 00:27:11

标签: c# wcf async-await

我知道我们通常应避免异步过同步,反之亦然。以下是Stephen Toub发表的两篇文章,很好地解释了这一点:

我们使用WCF跨层进行通信,并使用服务和客户端共享的合同。客户端使用ChannelFactory<TContract>来创建代理和通道。这样做的一大好处是我们不必手动更新[许多]服务引用,如果接口发生变化,我们会在双方都进行自动编译时检查。但是,这也意味着我们不能保持服务器端接口同步(不返回Task<Result>),并且客户端代理也是异步的(由于网络跳跃而返回Task<Result>)。

所以我的问题是,合同返回类型Task<Result>是否有任何真正的危害/缺点,而在服务器端只需要return Task.FromResult(SyncCode());?我们在服务器端有效地进行异步过度同步以在客户端启用异步,但无论如何,网络在技术上已经是异步。 Task.FromResult()不应创建任何其他线程或引入任何重大开销。这似乎是规则的合理例外吗?

换句话说,我可能有类似以下的实现:

public PersonResult GetPerson(int id)
{
    return SyncCode();
}

public Task<PersonResult> GetPersonAsync(int id)
{
    return Task.FromResult(GetPerson(id));
}

2 个答案:

答案 0 :(得分:2)

  

Task.FromResult()不应该创建任何其他线程或   引入任何重大开销。这看起来是否合理   规则例外?

不,这不是一个合理的例外(如果您有选择),因为它会损害您的WCF服务的可伸缩性。在可用的情况下,在服务器端使用自然异步API符合您的最佳利益。

对于客户端,如果您将WCF合同接口方法定义为PersonResult GetPerson(int id)Task<PersonResult> GetPersonAsync(int id),则无关紧要。即使不重新编译WCF代理,客户端也可以以任何一种方式工作。有关详细信息:

WCF客户端中的异步完全独立于WCF服务中的异步。通常,您希望在双方都使用异步,但出于不同的原因:在客户端应用程序中保持UI响应,并增加服务器端的吞吐量。有关详细信息:

答案 1 :(得分:1)

我的示例代码不允许激活服务,因为附加Async被视为相同的方法名称。错误是,&#34;不能在同一个合同中使用相同名称的两个操作,类型为GetPersonAsync和GetPerson的方法违反此规则。&#34;

从错误消息中我发现了一个更好的解决方案:https://stackoverflow.com/a/28635558/177333。您有一个在服务器端实现的同步接口,并创建一个派生接口,为客户端添加异步。由于WCF在通过网络发送邮件时忽略了名称中的Async,因此无论如何都要调用相同的方法。