本文转自:http://www.codeproject.com/Articles/70441/Calling-Web-Service-Functions-Asynchronously-from

Over on the ASP.NET forums where I moderate, a user had a problem calling a Web Service from a web page asynchronously. I tried his code on my machine and was able to reproduce the problem. I was able to solve his problem, but only after taking the long scenic route through some of the more perplexing nuances of Web Services and Proxies.

Here is the fascinating story of that journey.

Start with a Simple Web Service

 Collapse | Copy Code
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
// sleep 10 seconds
System.Threading.Thread.Sleep(10 * 1000);
return "Hello World";
}
}

The 10 second delay is added to make calling an asynchronous function more apparent. If you don't call the function asynchronously, it takes about 10 seconds for the page to be rendered back to the client. If the call is made from a Windows Forms application, the application freezes for about 10 seconds.

Add the web service to a web site. Right-click the project and select "Add Web Reference…"

Next, create a web page to call the Web Service.

Note: An ASP.NET web page that calls an 'Async' method must have the Async property set to true in the page's header:

 Collapse | Copy Code
<%@ Page Language="C#"
AutoEventWireup="true"
CodeFile="Default.aspx.cs"
Inherits="_Default"
Async='true'%>

Here is the code to create the Web Service proxy and connect the event handler. Shrewdly, we make the proxy object a member of the Page class so it remains instantiated between the various events.

 Collapse | Copy Code
public partial class _Default : System.Web.UI.Page
{
localhost.Service1 MyService; // web service proxy // ---- Page_Load --------------------------------- protected void Page_Load(object sender, EventArgs e)
{
MyService = new localhost.Service1();
MyService.HelloWorldCompleted += EventHandler;
}

Here is the code to invoke the web service and handle the event:

 Collapse | Copy Code
// ---- Async and EventHandler (delayed render) --------------------------

protected void ButtonHelloWorldAsync_Click(object sender, EventArgs e)
{
// blocks
ODS("Pre HelloWorldAsync...");
MyService.HelloWorldAsync();
ODS("Post HelloWorldAsync");
}
public void EventHandler(object sender, localhost.HelloWorldCompletedEventArgs e)
{
ODS("EventHandler");
ODS(" " + e.Result);
} // ---- ODS ------------------------------------------------
//// Helper function: Output Debug String public static void ODS(string Msg)
{
String Out = String.Format("{0} {1}",
DateTime.Now.ToString("hh:mm:ss.ff"), Msg);
System.Diagnostics.Debug.WriteLine(Out);
}

I added a utility function I use a lot: ODS (Output Debug String). Rather than include the library it is part of, I included it in the source file to keep this example simple.

Fire up the project, open up a debug output window, press the button and we get this in the debug output window:

 Collapse | Copy Code
11:29:37.94 Pre HelloWorldAsync...
11:29:37.94 Post HelloWorldAsync
11:29:48.94 EventHandler
11:29:48.94 Hello World

Sweet. The asynchronous call was made and returned immediately. About 10 seconds later, the event handler fires and we get the result. Perfect….right?

Not so fast cowboy. Watch the browser during the call:

What the heck? The page is waiting for 10 seconds. Even though the asynchronous call returned immediately,ASP.NET is waiting for the event to fire before it renders the page. This is NOT what we wanted.

I experimented with several techniques to work around this issue. Some may erroneously describe my behavior as 'hacking' but, since no ingesting of Twinkies was involved, I do not believe hacking is the appropriate term.

If you examine the proxy that was automatically created, you will find a synchronous call to HelloWorld along with an additional set of methods to make asynchronous calls. I tried the other asynchronous method supplied in the proxy:

 Collapse | Copy Code
// ---- Begin and CallBack ----------------------------------

protected void ButtonBeginHelloWorld_Click(object sender, EventArgs e)
{
ODS("Pre BeginHelloWorld...");
MyService.BeginHelloWorld(AsyncCallback, null);
ODS("Post BeginHelloWorld");
}
public void AsyncCallback(IAsyncResult ar)
{
String Result = MyService.EndHelloWorld(ar); ODS("AsyncCallback");
ODS(" " + Result);
}

The BeginHelloWorld function in the proxy requires a callback function as a parameter. I tested it and the debug output window looked like this:

 Collapse | Copy Code
04:40:58.57 Pre BeginHelloWorld...
04:40:58.57 Post BeginHelloWorld
04:41:08.58 AsyncCallback
04:41:08.58 Hello World

It works the same as before except for one critical difference: The page rendered immediately after the function call. I was worried the page object would be disposed after rendering the page but the system was smart enough to keep the page object in memory to handle the callback.

Both techniques have a use:

Delayed Render: Say you want to verify a credit card, look up shipping costs and confirm if an item is in stock. You could have three web service calls running in parallel and not render the page until all were finished. Nice. You can send information back to the client as part of the rendered page when all the services are finished.

Immediate Render: Say you just want to start a service running and return to the client. You can do that too. However, the page gets sent to the client before the service has finished running so you will not be able to update parts of the page when the service finishes running.

Summary

YourFunctionAsync() and an EventHandler will not render the page until the handler fires.

BeginYourFunction() and a CallBack function will render the page as soon as possible.

I found all this to be quite interesting and did a lot of searching and researching for documentation on this subject….but there isn't a lot out there. The biggest clues are the parameters that can be sent to the WSDL.exeprogram:

http://msdn.microsoft.com/en-us/library/7h3ystb6(VS.100).aspx

Two parameters are oldAsync and newAsyncOldAsync will create the Begin/End functions; newAsync will create the Async/Event functions. Caveat: I haven't tried this but it was stated in this article. I'll leave confirming this as an exercise for the student. 

Included Code

I'm including the complete test project I created to verify the findings. The project was created with VS 2008 SP1. There is a solution file with 3 projects, the 3 projects are:

  • Web Service
  • ASP.NET Application
  • Windows Forms Application

To decide which program runs, you right-click a project and select "Set as Startup Project".

I created and played with the Windows Forms application to see if it would reveal any secrets. I found that in the Windows Forms application, the generated proxy did NOT include the Begin/Callback functions. Those functions are only generated for ASP.NET pages. Probably for the reasons discussed earlier. Maybe those Microsoft boys and girls know what they are doing.

I hope someone finds this useful.

Steve Wellens 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

[转]Calling Web Service Functions Asynchronously from a Web Page 异步调用WebServices的更多相关文章

  1. vivo web service:亿万级规模web服务引擎架构

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/ovOS0l9U5svlUMfZoYFU9Q vivo web service是开发团队围绕奇点 ...

  2. 【转】基于CXF Java 搭建Web Service (Restful Web Service与基于SOAP的Web Service混合方案)

    转载:http://www.cnblogs.com/windwithlife/archive/2013/03/03/2942157.html 一,选择一个合适的,Web开发环境: 我选择的是Eclip ...

  3. 使用Eclipse自带Web Service插件(Axis1.4)生成Web Service服务端/客户端

    创建一个名字为math的Java web工程,并将WSDL文件拷入该工程中 将Axis所需的jar包拷贝至WebRoot\WEB-INF\lib目录下,这些jar包会自动导入math工程中 一,生成W ...

  4. Web Service学习之二:Web Service(for JAVA)的几种框架

    在讲Web Service开发服务时,需要介绍一个目前开发Web Service的几个框架,分别为Axis,axis2,Xfire,CXF以及JWS(也就是前面所述的JAX-WS,这是Java6发布所 ...

  5. Web Service 实例基于Socket创建Web服务

    ServerSocket服务器端代码如下: public static void main(String[] args) throws IOException { // 1:建立服务器端的tcp so ...

  6. Calling the Web Service dynamically (.NET 动态访问Web Service)

    针对.NET平台下的WebService访问,为达到不添加引用的情况下,动态调用外部服务. 主体方法: public class WebServiceHelper { //Calling the We ...

  7. .NET基础拾遗(7)Web Service的开发与应用基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...

  8. Web Service概念梳理

    计算机技术难理解的很多,Web Service 对我来说就是一个很难理解的概念:为了弄清它到底是什么,我花费了两周的时间,总算有了一些收获,参考了不少网上的资料,但有些概念说法不一.我以w3c和 一些 ...

  9. Web Service随笔

    什么是Web Service? WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络 ...

随机推荐

  1. JavaScript或jQuery模拟点击超链接和按钮

    有时候我们需要页面自动点击超链接或者按钮,可以用js或者jQuery利用程序去点击,方法很简单,按钮或超链接代码如下: <a href="url" target=" ...

  2. Java数据类型和运算符

    一,数据类型分类(2种) 1. 基本数据类型(3种) 数值型: 整数类型(4种): byte(1字节):范围(-128~127): short(2字节):范围(-32768~32767): int(4 ...

  3. [Linux] Linux进程PID散列表

    linux系统中每个进程由一个进程id标识,在内核中对应一个task_struct结构的进程描述符,系统中所有进程的task_struct通过链表链接在一起,在内核中,经常需要通过进程id来获取进程描 ...

  4. vs 附加包含目录属性

    如果是在属性页里头添加了路径,则当程序拷贝到其他电脑上头的话,这个包含目录仍然存在,这就是与添加环境变量的区别.如果是通过添加环境变量配置的路径,则换了台电脑,这个路径就没有了,需要重新配置.

  5. 最小的N个和(codevs 1245)

    1245 最小的N个和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 有两个长度为 N ...

  6. Android实现电子邮箱客户端

    本文主要讲述了安卓平台上利用QQ邮箱SMTP协议,POP3协议发送与接收消息的实现 发送邮件核心代码 import java.security.Security; import java.util.D ...

  7. .net学习之.net和C#关系、运行过程、数据类型、类型转换、值类型和引用类型、数组以及方法参数等

    1..net 和 C# 的关系.net 是一个平台,C#是种语言,C#语言可以通过.net平台来编写.部署.运行.net应用程序,C#通过.net平台开发.net应用程序2..net平台的重要组成FC ...

  8. 国家与城市的sql

    --省表 create table tb_province ( pID int NOT NULL PRIMARY KEY, pName ) ) --省 ,'北京市') ,'天津市') ,'上海市') ...

  9. XML的验证模式

    XML文件的验证模式保证了XML文件的正确性,而比较常用的验证模式有两种:DTD和XSD. DTD与XSD区别 DTD(Document Type Definition)即文档类型定义,是一种XML约 ...

  10. 贪心 赛码 1001 Movie

    题目传送门 /* 贪心:官方题解: 首先我们考虑如何选择最左边的一个区间 假设最左边的区间标号是i, 那选择的另外两个区间的左端点必定要大于Ri 若存在i之外的j, 满足Rj<Ri, 那么另外两 ...