• WCF异步调用实战:OneWay+Asynchronous Operation


    最近,博客园博客评论、博问回答、闪存都会出现同样的问题,有时提交特别慢,甚至一次提交长达6秒左右。

    通过日志分析发现,引起速度慢的操作发生在调用WCF服务时。比如,我在一篇博文中发表了一个评论,评论内容被保存到数据库之后,还会调用WCF服务,生成一条“博客评论”动态,这样在园子里关注我的人就能看到这条动态。

    由于动态的操作频繁,数据量大,是一个相对耗时的操作,我们希望这个操作不要影响当前程序的执行,所以,采用异步操作是一个合理的选择。而且这是一个不需要返回值的异步操作。

    我们想当然地在WCF客户端生成代理类时选择了“Generate asynchronous operations”,生成了客户端异步操作的代理类,然后调用异步方法client.AddAsync()。

    可是,采用这样的异步调用之后,发现问题依然存在。

    这种异步调用方法叫“异步信道调用”:

    客户端通过绑定创建的信道向服务端发送消息,从而实现了对服务的调用,不管消息通过信道向服务端发送的方式是同步的(采用请求-回复MEP进行消息交换)还是异步的(采用单向MEP进行消息交换),客户端程序都可以通过代理对象异步地调用信道,从而实现异步服务调用;

    欲解详情,请移步Artech的博客 ...-》WCF技术剖析之十一:异步操作在WCF中的应用(上篇)

    这个异步调用是针对信道(Channel)的,与服务端无关,也就是WCF客户端改为异步之后,服务端不需要作任何修改。

    此路不通,只能绕行...

    于是,我们改用WCF服务端异步,准确的说法是“异步服务实现”(服务端在具体实现服务操作的时候,采用异步调用的方式。- 引用自异步操作在WCF中的应用(上篇))。怎么实现呢?遇到WCF问题,当然要去园子里当之无愧的WCF专家博客。参考了WCF技术剖析之十一:异步操作在WCF中的应用(下篇),我们服务端的WCF也异步了。

    可是,惊喜没有出现,问题依旧。

    此路还是不通,只能继续绕行,问题是往哪里绕?

    我们通过测试进一步确认了问题,在WCF服务端实现方法中直接将当前线程sleep:

    Thread.Sleep(50000);

    经过测试发现,不管客户端是同步还异步,服务端是同步还是异步,都跳不过这个Sleep时间。难道是我们对这里的异步理解错了?(后来发现,的确是理解错了)

    遇到技术难题找Google,Google一般找StackOverflow(这两人感情很好),找到一个线索

    原来,之前的方法不管用什么步,都要等服务端的方法执行全部完成,而异步只是在发行异步调用之后,不用干等,可以干其他事情。但整个执行还是要等异步方法执行完成并返回。

    而我们的需求就发起异步调用之后,就走人,不管执行结果如何,这样才能保证异步调用对当前程序的执行速度影响最小。

    而WCF已经考虑了这个需求,提供了解决方案:[OperationContract(IsOneWay = true)],见上图中的代码。

    回头看看Artech的文章,也提到了这个:

    单向(One-way)消息交换:客户端的信道通过单向的消息交换模式向服务端发送消息,消息一旦抵达传输层马上返回,从而达到异步服务调用的效果。

    绕行两次,终于走上正道!

    于是,采用OneWay解决方案,在服务端相应的WCF接口上加上[OperationContract(IsOneWay = true)]。

    需要注意的地方:

    • 标记为[OperationContract(IsOneWay = true)]的方法返回值必须为void。
    • WCF客户端要重新生成代理类。

    测试下来,发现偶尔还会出现调用WCF速度慢的问题。后来,将客户端改为“异步信道调用”(Asynchronous Operation),也就是前面所述的第一种异步调用方法(client.AddAsync()),问题才解决。

    所以,经验实践检验过的解决方案是单向(One-way)消息交换+“异步信道调用”(Asynchronous Operation)

    小结

    在遇到问题并进行解决的时候,是学习效率最高、学习热情最高的时候,不要急于求成,将问题相关的知识理解透了,解决方法会突然而至。问题解决之后,写一篇博客,将在解决问题过程中学到的知识整理一下,将零散的知识点组织起来,你将会有更进一步的收获。

    在解决问题中学习,在解决问题后分享,在学习与分享中成长!

  • 相关阅读:
    HTML里使用CSS 的几种方式?
    Dmoz介绍及怎么提交?
    delphi实现自动填写表单和调用网页上的函数
    SEO之Head标签
    location.replace()和location.href=的区别?
    css几种选择器举例
    如何让百度认为你的站是一个好网站?
    桌面被恶意软件放上几个ie图标删除不了怎么办?
    Delphi正则表达式使用方法(TPerlRegEx)
    mysql中limit的用法详解(数据分页常用)
  • 原文地址:https://www.cnblogs.com/dudu/p/wcf_async.html
Copyright © 2020-2023  润新知