加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用异步方式调用WebService

发布时间:2020-12-17 02:58:14 所属栏目:安全 来源:网络整理
导读:?????? 在很多情况下我们可能都要使用异步调用WEBService。使用异步的好处是非阻塞方式进行的。当然也增加一定的编程难度。使用异步编程,我们可以实现对远程服务的调用,查询调用状态,或取消调用等功能。 我们以代码实例为例来解说 首先使用VS2k3建立一个W

?????? 在很多情况下我们可能都要使用异步调用WEBService。使用异步的好处是非阻塞方式进行的。当然也增加一定的编程难度。使用异步编程,我们可以实现对远程服务的调用,查询调用状态,或取消调用等功能。

我们以代码实例为例来解说
首先使用VS2k3建立一个WEBSERVICE ,假设是一个提供股票信息的服务。这里我处理的比较简单,仅是模拟一下服务调用需要很长的时间。
namespace StockService
{
?/// <summary>
?/// Service1 的摘要说明。
?/// </summary>
?public class StockPrice : System.Web.Services.WebService
?{
??public StockPrice()
??{
???//CODEGEN: 该调用是 ASP.NET Web 服务设计器

所必需的
???InitializeComponent();
??}

??#region 组件设计器生成的代码
??
??//Web 服务设计器所必需的
??private IContainer components = null;
????
??/// <summary>
??/// 设计器支持所需的方法 - 不要使用代码编辑器修改
??/// 此方法的内容。
??/// </summary>
??private void InitializeComponent()
??{
??}

??/// <summary>
??/// 清理所有正在使用的资源。
??/// </summary>
??protected override void Dispose( bool disposing )
??{
???if(disposing && components != null)
???{
????components.Dispose();
???}
???base.Dispose(disposing);??
??}
??
??#endregion

??[WebMethod]
??public double getStockPrice(String stockSymbol)
??{
???//在这里我们进行模拟处理,线程暂停5秒
???Thread.Sleep(5000);
???return new Random().NextDouble() + 15.0;
??}
??[WebMethod]
??public double getStockPrice1(String stockSymbol)
??{
???//在这里我们进行模拟处理,线程暂停5秒
???Thread.Sleep(5000);
???return new Random().NextDouble() + 15.0;
??}
??[WebMethod]
??public double getStockPrice2(String stockSymbol)
??{
???//在这里我们进行模拟处理,线程暂停5秒
???Thread.Sleep(5000);
???return new Random().NextDouble() + 15.0;
??}

?}
}


然后我们建立一个WINFORM程序来充当客户端调用刚才建立的WEBSERVICE。这里我们有很多种方式来实现异步调用(包括自己建立一个线程来调用服务,当服务完成后,使用delegate来实现事件的回调)。这种方法我们先排除掉。因为当你添加一个WEB引用到本地工程时,代理类里已实现了异步调用的代码。
?public class Form2 : System.Windows.Forms.Form
?{
??private localhost.StockPrice m_stockService;
??private IAsyncResult m_handle;
??private System.Windows.Forms.Button button1;
??private System.Windows.Forms.Button button2;
??private System.Windows.Forms.Button button3;
??private System.Windows.Forms.Button button4;
??private System.Windows.Forms.TextBox messageBox;
??private System.Windows.Forms.Button button5;
??private System.Windows.Forms.Button button6;?

??/// <summary>
??/// 必需的设计器变量。
??/// </summary>
??private System.ComponentModel.Container components = null;

??public Form2()
??{
???//
???// Windows 窗体设计器支持所必需的
???//
???InitializeComponent();

???//
???// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
???//
??}

??/// <summary>
??/// 清理所有正在使用的资源。
??/// </summary>
??protected override void Dispose( bool disposing )
??{
???if( disposing )
???{
????if(components != null)
????{
?????components.Dispose();
????}
???}
???base.Dispose( disposing );
??}

??#region Windows 窗体设计器生成的代码
??/// <summary>
??/// 设计器支持所需的方法 - 不要使用代码编辑器修改
??/// 此方法的内容。
??/// </summary>
??private void InitializeComponent()
??{
???this.messageBox = new System.Windows.Forms.TextBox();
???this.button1 = new System.Windows.Forms.Button();
???this.button2 = new System.Windows.Forms.Button();
???this.button3 = new System.Windows.Forms.Button();
???this.button4 = new System.Windows.Forms.Button();
???this.button5 = new System.Windows.Forms.Button();
???this.button6 = new System.Windows.Forms.Button();
???this.SuspendLayout();
???//
???// messageBox
???//
???this.messageBox.Location = new System.Drawing.Point(16,8);
???this.messageBox.Multiline = true;
???this.messageBox.Name = "messageBox";
???this.messageBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
???this.messageBox.Size = new System.Drawing.Size(656,320);
???this.messageBox.TabIndex = 0;
???this.messageBox.Text = "";
???//
???// button1
???//
???this.button1.Location = new System.Drawing.Point(24,344);
???this.button1.Name = "button1";
???this.button1.TabIndex = 1;
???this.button1.Text = "调用";
???this.button1.Click += new System.EventHandler(this.button1_Click);
???//
???// button2
???//
???this.button2.Location = new System.Drawing.Point(128,344);
???this.button2.Name = "button2";
???this.button2.TabIndex = 2;
???this.button2.Text = "轮询";
???this.button2.Click += new System.EventHandler(this.button2_Click);
???//
???// button3
???//
???this.button3.Location = new System.Drawing.Point(240,344);
???this.button3.Name = "button3";
???this.button3.TabIndex = 3;
???this.button3.Text = "中止";
???this.button3.Click += new System.EventHandler(this.button3_Click);
???//
???// button4
???//
???this.button4.Location = new System.Drawing.Point(352,344);
???this.button4.Name = "button4";
???this.button4.Size = new System.Drawing.Size(96,23);
???this.button4.TabIndex = 4;
???this.button4.Text = "等待异步操作";
???this.button4.Click += new System.EventHandler(this.button4_Click);
???//
???// button5
???//
???this.button5.Location = new System.Drawing.Point(464,344);
???this.button5.Name = "button5";
???this.button5.Size = new System.Drawing.Size(120,23);
???this.button5.TabIndex = 5;
???this.button5.Text = "一次调用三个服务";
???this.button5.Click += new System.EventHandler(this.button5_Click);
???//
???// button6
???//
???this.button6.Location = new System.Drawing.Point(608,344);
???this.button6.Name = "button6";
???this.button6.TabIndex = 6;
???this.button6.Text = "回调处理";
???this.button6.Click += new System.EventHandler(this.button6_Click);
???//
???// Form2
???//
???this.AutoScaleBaseSize = new System.Drawing.Size(6,14);
???this.ClientSize = new System.Drawing.Size(696,477);
???this.Controls.Add(this.button6);
???this.Controls.Add(this.button5);
???this.Controls.Add(this.button4);
???this.Controls.Add(this.button3);
???this.Controls.Add(this.button2);
???this.Controls.Add(this.button1);
???this.Controls.Add(this.messageBox);
???this.Name = "Form2";
???this.Text = "Form2";
???this.Load += new System.EventHandler(this.Form2_Load);
???this.ResumeLayout(false);

??}
??#endregion

??private void Form2_Load(object sender,System.EventArgs e)
??{
??
??}

??//你调用BegingetStockPrice()后得到一个具有IAsyncResult界面的对象。
??//它提供了IsCompleted的属性。当这个值为"True"的时候,
??//你就可以通过调用EndgetStockPrice()来拿到函数运行的结果。
??//更重要的是,你可以在异步调用的时候"放弃Abort"调用。
??//下面的程序段是用3个"按钮(Button)"来示意如何使用异步调用,检查调用是否结束以及放弃调用。

??//异步调用WebMethod
??private void button1_Click(object sender,System.EventArgs e)
??{
???m_stockService = new localhost.StockPrice();
???m_handle = m_stockService.BegingetStockPrice("IBM",null,null);
???messageBox.Text += "正在调用WEB服务." + System.Environment.NewLine;

??}
??//检查异步调用是否完成。如果完成的话,就取出调用结果
??private void button2_Click(object sender,System.EventArgs e)
??{
???if(m_handle==null)
???{
????messageBox.Text += "没有服务被调用!"+System.Environment.NewLine;
????return;
???}
???if(m_handle.IsCompleted == false)
????messageBox.Text += "服务正在调用中"? + System.Environment.NewLine;
???else
???{
????double price = m_stockService.EndgetStockPrice(m_handle);
????messageBox.Text += "金额为: " + price + System.Environment.NewLine;
???}

??}

??//放弃异步调用
??private void button3_Click(object sender,System.EventArgs e)
??{
???if(m_handle!=null)
???{
????WebClientAsyncResult result = (WebClientAsyncResult)m_handle;
????result.Abort();
????m_handle = null;
???}
???messageBox.Text += "调用服务被用户终止" + System.Environment.NewLine;

??}

??//使用WaitHandle
??//你调用BegingetStockPrice()后得到一个具有IAsyncResult界面的对象。
??//它提供了AsyncWaitHandle的属性。调用它的WaitOne()函数可以使程序被阻拦直到另外一个线程函数调用完成。
??//之后程序将继续往下执行。
??private void button4_Click(object sender,System.EventArgs e)
??{
???if(this.m_stockService ==null)
????m_stockService = new localhost.StockPrice();
???m_handle = m_stockService.BegingetStockPrice("IBM",null);
???messageBox.Text? += "正在调用服务" + System.Environment.NewLine;
???m_handle.AsyncWaitHandle.WaitOne();
???double price = m_stockService.EndgetStockPrice(m_handle);
???messageBox.Text += "金额为: " + price + System.Environment.NewLine;??

??}

??//从现象上看,和同步调用相比你并没有得到好处。程序等待的时候仍然处于"挂起"状态。
??//但是在有些情况下,"等待"还是有它的特色的。
??//比如说你可以连续调用三个WebMethod,如果每个函数费时5秒,
??//那么使用同步的话总共会使用15秒钟。但如果使用异步的话,你可能只要等待5秒钟。
??//当然这要使用WaitHandle提供的WaitAll()函数。如下所示:
??//一次调用三个服务
??private void button5_Click(object sender,System.EventArgs e)
??{
???
???if(this.m_stockService ==null)
????m_stockService = new localhost.StockPrice();
???IAsyncResult[] handles = new IAsyncResult[3];
??
???messageBox.Text? += "一次调用三个服务:开始时间为"+DateTime.Now.ToString() + System.Environment.NewLine;
???handles[0] = m_stockService.BegingetStockPrice("IBM",null);
???handles[1] = m_stockService.BegingetStockPrice1("MS",null);
???handles[2] = m_stockService.BegingetStockPrice2("SUN",null);
???
???WaitHandle[] WaitHandles ={
????handles[0].AsyncWaitHandle,
????handles[1].AsyncWaitHandle,
????handles[2].AsyncWaitHandle};
??
???//函数被阻拦,直到3个函数都执行完毕。WaitAny()函数情况类似,但有一个函数完成后
???//程序就解阻,继续往下执行
???WaitHandle.WaitAll(WaitHandles);
???messageBox.Text+="调用完成时间为:"+DateTime.Now.ToString()+ System.Environment.NewLine;
???double[] prices = new double[3];
???for(int i=0;i<3;i++)
???{
????prices[i] = m_stockService.EndgetStockPrice(handles[i]);??
????messageBox.Text += "金额为: " + prices[i] +
?????System.Environment.NewLine;
???}
???messageBox.Text? += "调用三个服务完毕:" + System.Environment.NewLine;
??}

??//看到现在,你可能还没有感到满意。因为你异步调用了函数后,还要手工检查函数是否执行完毕,
??//或者要处于等待状态。能否让函数完成后,自动显示结果或是做其它操作呢?
??//答案是"能"的。回调函数就是做这种事情的。
??private void button6_Click(object sender,System.EventArgs e)
??{
???if(this.m_stockService ==null)
????m_stockService = new localhost.StockPrice();
???//生成回调函数
???AsyncCallback cb = new AsyncCallback (this.callback);
???m_stockService.BegingetStockPrice("IBM",cb,DateTime.Now);
???messageBox.Text? += "远程服务被调用" + System.Environment.NewLine;

??}??private void callback(IAsyncResult handle)??{???double price = m_stockService.EndgetStockPrice(handle);???lock(this)???{????messageBox.Text += "金额为: " + price + ". 请求时间: " +?????handle.AsyncState.ToString() + ",结束时间: " +?????DateTime.Now.ToString() +?????System.Environment.NewLine;???}??}?}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读