【问题标题】:How can I implement client-side async calls with WCF's ChannelFactory<T>?如何使用 WCF 的 ChannelFactory<T> 实现客户端异步调用?
【发布时间】:2014-04-18 04:57:07
【问题描述】:

假设我们正在使用 WCF 的 ChannelFactory 为 Calculator Web 服务编写客户端。服务契约通过实现服务和客户端引用的第三个程序集共享。以下是服务合同(不能更改!)

public interface ICalculator 
{
    int Add(int x, int y);
}

ChannelFactory 创建一个透明代理对象,它“模拟” ICalculator 服务契约,将方法调用传递给 RealProxy 对象,该对象随后将消息发送到 WCF 通道堆栈。有没有办法操纵 WCF(仅在客户端!)以自动公开对任务友好的服务操作,类似于 VS 自动生成的服务代理?

需要明确的是,无论如何我都不打算将我的服务修改为对异步友好的。我希望我的客户在等待通常阻塞的服务调用完成时继续处理。

【问题讨论】:

    标签: .net web-services wcf asynchronous


    【解决方案1】:
    public interface ICalculator 
    {
        Task<int> Add(int x, int y);
    }
    

    将此作为合同。但是,您需要确保您运行的是 .net 4.5 才能使其正常工作。

    记住在服务器端使用这种模式

    public class Calculator : ICalulator
    {
        public Task<int> Add(int x, int y)
        {
            int result = x + y;
            return Task.FromResult(result);
        }
    }
    

    【讨论】:

    • 请重新阅读我的帖子,我提到我不能更改合同,也不想更改。我不想在不必要的时候公开 Task 。无论其方法签名如何,我都应该能够等待任何服务操作,因为它是一个非常类似于流式传输的 I/O 操作。
    • 为了证明客户端可以随时等待任何服务调用,请参阅 VS 的自动生成服务代理实现。我基本上想要那个,但使用 ChannelFactory.
    • 您需要在客户端“公开”一个任务,因为您需要在调用点进行异步,以确保无线程异步(否则您只能获得并发异步)。我演示了如何在服务器端实现同步调用。如果您想在不更改服务合同的情况下实现此目的,我建议您使用服务引用来创建您的界面,以减少手动步骤。
    • 查看我对您对此问题/主题的“答案”的类似评论的评论回复,因为它也适用于您在此处的最新评论。
    【解决方案2】:

    我使用 ILSpy 进行了一些探索,发现 ChannelFactory 和 VS 的服务代理代码都利用底层的相同代码为 ICalculator 生成透明代理。唯一的区别是自动生成代码创建了一个自定义接口,该接口反映了服务的契约,加上 Task 异步方法,其 OperationContract 属性指向“真正的”服务操作 URI。

    [ServiceContract]
    public interface ICalculatorClient
    {
        [ServiceOperation(Action="http://tempuri.org/ICalculator/Add")]
        Task<int> AddAsync(int x, int y);
    }
    

    因此,我没有使用包含原始服务的服务合同的程序集,而是在客户端代码中创建了自己的 ICalculatorClient 服务合同(名称只是为了消除此测试的歧义),其中包含所需的 Task 异步方法调用,仅具有必需的 ServiceOperation 属性和 Action 属性,该属性指向服务器合同上“真实”服务操作的 URI。

    在运行时,观察到了预期的行为:我的客户端代码在等待来自服务器的响应时继续运行,它最终按预期收到了响应。该服务并不明智,没有经过修改以满足客户的需求。客户端更加智能,可以控制其与 Web 服务交互的细节。

    【讨论】:

    • 简而言之,您将失去使用共享合同程序集而不是使用添加服务参考的所有优势。
    • 我不同意。服务引用有很多缺点。还有其他方法可以重新获得 T4 模板等自动生成代码的便利性,而不受代理施加的限制:请参阅此 MSDN 文章:blogs.msdn.com/b/juveriak/archive/2008/02/03/…
    • T4 不适用于 cs 文件中的接口(尝试让 CodeDom 理解部分),只是被 dll 反射破坏了(dll 读取锁会阻止你编译)。与 Roslyn 一起使用的 T4 可能会起作用,但我从未使用过它。我从不建议你使用代理。我更喜欢渠道工厂。我只建议你生成带有服务参考的合同。
    • 有趣的建议,阿伦。我从没想过运行代码生成只是为了提取一个接口,然后使用 ChannelFactory。对于一种常见的做法,这可能是两全其美的做法。如果您编辑您的答案以反映这一点,我会非常乐意给您“答案”标记。
    猜你喜欢
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多