异步调用WEBSERVICE

这篇博客详细介绍了如何使用Begin/End调用模式和事件驱动的异步模式来调用Web服务。在Begin/End模式中,通过WaitHandle等待或回调函数实现异步通信,而在事件驱动模式下,创建事件处理程序并在Web服务方法返回时执行代码。这两种方式都在.NET 3.5环境下进行了示例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步调用WEBSERVICE

Web 服务描述语言工具 (Wsdl.exe) 生成客户端代理类来访问指定的 Web 服务时,会为该代理类提供与每个 Web 服务方法进行异步通信的两种机制。第一种机制是 Begin/End 模式。第二种机制是在 .NET Framework 2.0 版中提供的事件驱动的异步编程模式。

Begin/End 调用模式

Wsdl.exe Web 服务中发布的每项操作自动创建三个方法(ASP.NET 中的 Web 服务方法)。一个方法针对同步访问;另外两个方法针对异步访问。即使该 Web 服务方法只有一个同步实现也不例外。下表对这三个方法进行了说明:

代理类中方法的名

说明

<NameOfWebServiceMethod>

为名为 <NameOfWebServiceMethod> Web 服务方法同步发送消息

Begin<NameOfWebServiceMethod>

开始与名为 <NameOfWebServiceMethod> Web 服务方法的异步消息通信。客户端指示 Begin 方法开始对服务调用进行处理,但立即返回。返回值不是 Web 服务方法指定的数据类型,而是实现 IAsyncResult 接口的类型

End <NameOfWebServiceMethod>

结束与名为 <NameOfWebServiceMethod> Web 服务方法的异步消息通信,返回的值是 Web 服务方法调用的结果

Begin End 方法均遵循 .NET Framework 异步设计模式的命名约定。该设计模式规定每种同步方法有两种如此命名的异步方法

使用 Begin/End 模式实现进行异步方法调用的 Web 服务客户

客户端如何知道何时调用 End 方法呢?根据 .NET Framework 的定义,有两种方法可以使客户端确定这一点:

·         等待方法:使用 WaitHandle 类的方法之一使客户端等待方法完成。

·         回调方法:向 Begin 方法传递一个回调函数,在该方法完成处理后再调用该函数来检索结果。

注意:无论客户端选择两种方法中的哪一种与 Web 服务进行异步通信,收发的 SOAP 消息都与通过同步代理方法生成的 SOAP 消息相同。也就是说,仍然只有一个 SOAP 请求和 SOAP 响应通过网络发送和接收。代理类通过使用与客户端调用 Begin 方法时使用的线程不同的线程来处理 SOAP 响应,从而实现该目的。因此,在代理类接收和处理 SOAP 响应时,客户端可以在其线程上继续执行其他工作

使用 Begin/End 模式的等待方

WaitHandle 类实现下列支持等待同步对象得到信号通知的方法:WaitOneWaitAny WaitAll。当同步对象得到信号通知时,表示等待指定资源的线程此时可以访问该资源了。Web 服务客户端通过 Begin 方法返回的 IAsyncResult 对象的 AsyncWaitHandle 属性,来访问 WaitHandle 对象

具体做法:

1、 Web 服务客户端调用所生成的代理类的 Begin 方法

IAsyncResult ar = pf.BeginFactorize(factorizableNum, null, null);

2、 Web 服务客户端通过返回的 IAsyncResult AsyncWaitHandle 属性来访问 WaitHandle 对象。

ar.AsyncWaitHandle.WaitOne()

3、 等待方法返回后,客户端调用 End 方法来获取结果。

results = pf.EndFactorize(ar);

使用 Begin/End 模式的回调方

具体做法:

  •           定义实现 AsyncCallback 委托的回调函数。

public static void FactorizeCallback(IAsyncResult ar)

  •       实例化 AsyncCallback 委托。

AsyncCallback cb = new AsyncCallback(TestCallback.FactorizeCallback);

  • 调用 Begin 方法,将回调函数作为第二个参数传递,将提供状态的对象(在本示例中是 PrimeFactorizer 的客户端实现)作为第三个参数传递。

IAsyncResult ar = pf.BeginFactorize(factorizableNum, cb, pf);

  • Begin 方法返回的 IAsyncResult 上检查 IsCompleted 属性。如果客户端已收到服务器的响应,该值将设置为 true
  • 在回调函数中访问状态对象。IAsyncState 参数的 AsyncState 属性将该对象作为第三个参数传递给 Begin 方法。

PrimeFactorizer pf = (PrimeFactorizer) ar.AsyncState;

  • 在回调函数中,对上一步中获取的状态对象调用 End 方法。

long[] results = pf.EndFactorize(ar);

使用事件驱动的异步模式的异步 Web 服务客户

Web 服务代理类中的每个 Web 方法都具有一个异步的对应版本。代理类自动生成每个 Web 方法的异步方法和对应事件。当异步方法被调用时,它将在另一个线程上执行,并在返回时引发对应的事件。您可以为异步方法的对应事件创建一个处理程序,从而 在它返回时执行代码

此模型可以简化生成多线程应用程序的过程,因为您不必自己实现复杂的多线程代码

具体做法:

1、 创建MethodCompleted 件。

private void HelloWorldCompleted(Object sender,

    localhost.HelloWorldCompletedEventArgs Completed)

    {

        // Insert code to implement the method here

    }

2、 向该事件的处理程序列表添加 MethodCompleted 事件处理程序。

myWebService.HelloWorldCompleted += new localhost.HelloWorldCompletedEventHandler(HelloWorldCompleted);
  
  

3、 使用该方法的 MethodAsync 形式调用 Web .

HelloWorldAsync();
  
  

 

注意,在net3.0中请将 ASP.NET 页面@ Page 指令中的Async设置为 true


  
  
   
    
  
  

示例代码[环境VS2008+NET3.5]

1、 webserviceWebService.asmx示例代码。

    using  System;
using  System.Collections;
using  System.Linq;
using  System.Web;
using  System.Web.Services;
using  System.Web.Services.Protocols;
using  System.Xml.Linq;
using  System.Threading;

/// <summary>
/// Summary description for WebService
/// </summary>

[WebService(Namespace  =   " http://tempuri.org/ " )]
[WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
//  To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
//  [System.Web.Script.Services.ScriptService]
public   class  WebService : System.Web.Services.WebService
{

    
public WebService()
    
{
        
//Uncomment the following line if using designed components 
        
//InitializeComponent(); 
    }


    [WebMethod]
    
public string HelloWorld()
    
{
        Thread.Sleep(
2000); //停留2秒.
        return "Hello World";
    }


}


2、 webPageWSTest.aspx

a.       ASPX

<% @ Page Language = " C# "  AutoEventWireup = " true "  Async = " true "  CodeFile = " WSTest.aspx.cs "  Inherits = " WSTest "   %>

<! DOCTYPE html PUBLIC  " -//W3C//DTD XHTML 1.0 Transitional//EN "   " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >

< html xmlns = " http://www.w3.org/1999/xhtml " >
< head runat = " server " >
    
< title > 异步调用WEBSERVICE示例代码 </ title >
</ head >
< body >
    
< form id = " form1 "  runat = " server " >
    
< div >
    
        
< asp:Button ID = " EventDriveButton "  runat = " server "  Text = " 事件驱动的异步模式 "  
            onclick
= " EventDriveButton_Click "   />
    
    
& nbsp; < asp:Button ID = " BeginEndWaitButton "  runat = " server "  Text = " Begin/End 模式等待技术 "  
            onclick
= " BeginEndWaitButton_Click "   />
        
& nbsp; < asp:Button ID = " BeginEndCallBackButton "  runat = " server "  
            Text
= " Begin/End 模式回调技术 "  onclick = " BeginEndCallBackButton_Click "   />
    
    
</ div >
    
</ form >
</ body >
</ html >

 

b.      CS

 

using  System;
using  System.Collections;
using  System.Configuration;
using  System.Data;
using  System.Linq;
using  System.Web;
using  System.Web.Security;
using  System.Web.UI;
using  System.Web.UI.HtmlControls;
using  System.Web.UI.WebControls;
using  System.Web.UI.WebControls.WebParts;
using  System.Xml.Linq;
using  System.Threading;
using  LocalService;
public   partial   class  WSTest : System.Web.UI.Page
{
  
    
protected void Page_Load(object sender, EventArgs e)
    
{
    }

    
/// <summary>
    
/// 事件驱动的异步模式的异步 
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>

    protected void EventDriveButton_Click(object sender, EventArgs e)
    
{
        Response.Write(
"事件驱动的异步模式的异步 <BR>");
        LocalService.WebService localService 
= new LocalService.WebService(); //创建代理类对象。
        localService.HelloWorldCompleted += new LocalService.HelloWorldCompletedEventHandler((o, a) => { Response.Write(string.Format("完成时间:{0}。 结果{1}<Br>", DateTime.Now.ToString("mm:ss.ffff"), a.Result)); });//创建事件。写结果与运行事件
        Response.Write(string.Format("开始调用时间:{0}<Br>", DateTime.Now.ToString("mm:ss.ffff")));//开始调用事件
        localService.HelloWorldAsync();//异步调用
        Response.Write(string.Format("调用结束时间:{0}<Br>", DateTime.Now.ToString("mm:ss.ffff")));   
        Thread.Sleep(
4000);//等待异步操作完成
    }

    
/// <summary>
    
/// 使用 Begin/End 模式的等待技术
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>

    protected void BeginEndWaitButton_Click(object sender, EventArgs e)
    
{
        LocalService.WebService localService 
= new LocalService.WebService(); //创建代理类对象。
        Response.Write("Begin/End 模式的等待技术<BR>");
        Response.Write(
string.Format("开始调用时间:{0}<Br>", DateTime.Now.ToString("mm:ss.ffff")));//开始调用事件
        IAsyncResult ar = localService.BeginHelloWorld(s => { }null);
        Response.Write(
string.Format("调用结束时间:{0}<Br>", DateTime.Now.ToString("mm:ss.ffff")));  
        ar.AsyncWaitHandle.WaitOne();
        
string result = localService.EndHelloWorld(ar);
        Response.Write(
string.Format("完成时间:{0}。 结果{1}<Br>", DateTime.Now.ToString("mm:ss.ffff"), result));
    }

    
/// <summary>
    
/// 使用 Begin/End 模式的回调技术
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>

    protected void BeginEndCallBackButton_Click(object sender, EventArgs e)
    
{    
        Response.Write(
"Begin/End 模式的回调技术<BR>");
        LocalService.WebService localService 
= new LocalService.WebService(); //创建代理类对象。
        Response.Write(string.Format("开始调用时间:{0}<Br>", DateTime.Now.ToString("mm:ss.ffff")));//开始调用事件
        IAsyncResult ar = localService.BeginHelloWorld(helloWorldCallBack, localService);
        Response.Write(
string.Format("调用结束时间:{0}<Br>", DateTime.Now.ToString("mm:ss.ffff")));
        
while (!ar.IsCompleted) { }//空循环等待完成
    }

    
private void helloWorldCallBack(IAsyncResult ar)
    
{
        LocalService.WebService ws 
= (LocalService.WebService)ar.AsyncState;
         
string result=  ws.EndHelloWorld(ar);
        Response.Write(
string.Format("完成时间:{0}。 结果{1}<Br>", DateTime.Now.ToString("mm:ss.ffff"), result));
    }

}

 

  感谢浏览,欢迎评论,转载请保留作者!  http://blog.youkuaiyun.com/Wgf2006/
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值