我知道我们通常应避免异步过同步,反之亦然。以下是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));
}
答案 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
,因此无论如何都要调用相同的方法。