`
阿尔萨斯
  • 浏览: 4170480 次
社区版块
存档分类
最新评论

NET应用程序中异步调用Web Service的几种方法

 
阅读更多

摘要

想必做.NET下开发的人对调用Web Service并不陌生,本文不介绍Web Service如何编写,只介绍.NET 应用程序中如何异步调用Web Service的几种方法。示例采用Windows应用程序。异步调用很有用,可以让客户端调用Web Service时(一般耗时未知),不至于阻塞客户端的UI线程导致假死的样子,还可以在调用Web Service的同时做些其它的处理。希望能对大家有所帮助,借此提出更好的解决方法。

测试程序界面

<shapetype coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f" id="_x0000_t75"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape type="#_x0000_t75" style="width: 228.75pt; height: 168.75pt;" id="_x0000_i1025"><imagedata src="file:///C:%5CDOCUME%7E1%5CADMINI%7E1.KOS%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.jpg" o:title="Async1"></imagedata></shape>

图一,调用前界面

<shape type="#_x0000_t75" style="width: 228pt; height: 245.25pt;" id="_x0000_i1026"><imagedata src="file:///C:%5CDOCUME%7E1%5CADMINI%7E1.KOS%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_image002.jpg" o:title="Async2"></imagedata></shape>

图二,调用后界面

详细代码实现

闲言少叙,直接进入主题吧。首先一个声明一个类(将来在客户端与服务器间传递):

publicclassClass1
...{
privateint_ID;
privatestring_Name;
publicintID
...{
get
...{
return_ID;
}

set
...{
_ID
=value;
}

}


publicstringName
...{
get
...{
return_Name;
}

set
...{
_Name
=value;
}

}

}

其次,声明一个Web方法:

//省略系统生成的WebService声明代码,采用默认的

publicclassService1:System.Web.Services.WebService

{

//省略系统生成的WebService声明代码,采用默认的

[WebMethod]

publicClass1GetClass1(intp_TimeSpan)

{

System.Threading.Thread.Sleep(p_TimeSpan);
//线程停止一段执行,假设一段处理的时间

Class1r
=newClass1();

r.Name
="AsyncCall";

r.ID
=p_TimeSpan;

returnr;

}

}

客户端调用代码,设计一个Windows Form窗体来测试,放入3个按钮控件(分别代表3种异步调用方法),一个进度条控件(表示调用Web Service后,客户端继续进行某些操作)。先把3种方法介绍一下:

1. 利用Backgroundworker对象,所在命名空间System.ComponentModelMSDN原文解释:BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。

2. 利用wsdl.exe生成Web Service的客户端代理类,调用其中WebMethodAsync方法。

3. 利用wsdl.exe生成Web Service的客户端代理类,分别调用其中WebMethodBeginEnd方法。

先用wsdl.exe把上面的Web Service生成客户端代理类并把他编译成类库引入Windows应用项目(这里我没有编译类库,而是直接把代理类.cs文件加入到了Windows应用项目中)。

进入Visual Studio命令行模式,运行

wsdl /out:MyService.cs http://localhost:2732/Service1.asmx

参数说明:第二个参数是Web ServiceURL,这个是我机器的本地环境,其他人需要根据情况修改!

注:第一种方式的调用,不采用手动生成Web Service客户端代理类也可以(项目中直接添加Web引用)。后面两种方法都是通过Web Service代理类中提供的方法实现,因此必须生成这个代理类。

看一下处理进度条控件值的代码,几种调用方法都会用到,

privatevoidChangeProcessBar()

{

for(inti=0;i<10;i++)

{

progressBar1.Value
=i;

//不知道用多少时间,慢慢走吧:)

System.Threading.Thread.Sleep(
500);

}

}



第一种方式调用,

privatevoidbutton1_Click(objectsender,EventArgse)

{

AsyncCall_In_Backgroundworker();

}



#regionAsyncCall_In_Backgroundworker

privatevoidAsyncCall_In_Backgroundworker()

{

BackgroundWorkerbackgroundworker
=newBackgroundWorker();

backgroundworker.DoWork
+=newDoWorkEventHandler(back_DoWork);//注册具体异步处理的方法

backgroundworker.RunWorkerCompleted
+=newRunWorkerCompletedEventHandler(back_RunWorkerCompleted);//注册调用完成后的回调方法

backgroundworker.RunWorkerAsync();
//这里开始异步调用

ChangeProcessBar();
//调用同时客户端处理不停止

}



voidback_RunWorkerCompleted(objectsender,RunWorkerCompletedEventArgse)

{

if(e.Error!=null)

throwe.Error;

progressBar1.Value
=progressBar1.Maximum;//调用完成了,把客户端进度条填充满

Class1result
=e.ResultasClass1;//结果转化为Class1对象

MessageBox.Show(
"IDis"+(result.ID.ToString()+",Nameis"+result.Name.ToString()));//显示从服务器获取的对象值

}



voidback_DoWork(objectsender,DoWorkEventArgse)

{

Service1service1
=newService1();//WebService代理类

e.Result
=service1.GetClass1(2500);//调用Web方法GetClass1,结果赋值给DoWorkEventArgs的Result对象

}

#endregion

第二种方式调用,

privatevoidbutton2_Click(objectsender,EventArgse)

{

AsynCall_In_WebServiceProxy();

}



#regionAsynCall_In_WebServiceProxy

privatevoidAsynCall_In_WebServiceProxy()

{

Service1service1
=newService1();//WebService代理类

service1.GetClass1Async(
3000);//这里开始异步调用

service1.GetClass1Completed
+=newGetClass1CompletedEventHandler(s_GetClass1Completed);//注册调用完成后的回调方法

ChangeProcessBar();
//调用同时客户端处理不停止

}



voids_GetClass1Completed(objectsender,GetClass1CompletedEventArgse)

{

if(e.Error!=null)

throwe.Error;

progressBar1.Value
=progressBar1.Maximum;//调用完成了,把客户端进度条填充满

Class1result
=e.ResultasClass1;//结果转化为Class1对象

MessageBox.Show(
"IDis"+(result.ID.ToString()+",Nameis"+result.Name.ToString()));//显示从服务器获取的对象值

}

#endregion

第三种调用,

privatevoidbutton3_Click(objectsender,EventArgse)

{

AsynCall_In_WebServiceProxyOther();

}



#regionAsynCall_In_WebServiceProxyOther

privatevoidAsynCall_In_WebServiceProxyOther()

{

Service1service1
=newService1();//WebService代理类

service1.BeginGetClass1(
3000,OnWebMethodCompleted,null);//这里开始异步调用

ChangeProcessBar();
//调用同时客户端处理不停止

}



privatevoidOnWebMethodCompleted(IAsyncResultp_AsyncResult)

{
//方法声明必须带有IAsyncResult类型对象

Service1service1
=newService1();//WebService代理类

Class1result
=service1.EndGetClass1(p_AsyncResult);//结束调用时结果返回

MessageBox.Show(
"IDis"+(result.ID.ToString()+",Nameis"+result.Name.ToString()));//显示从服务器获取的对象值

}

#endregion

细心的读者可能发现第三种方法并没有在调用完成后把客户端的进度条填满,的确在OnWebMethodCompleted中调用progressBar1.Value = progressBar1.Maximum时会出现InvalidOperationException异常,线程间操作无效: 从不是创建控件“progressBar1”的线程访问它。这个异常恐怕在.net下写过多线程操作的人都看到过 :)。可以声明一个委托,把处理进度条的代码放到一个方法中,用窗体的Invoke去安全的调用它。好下面把修改的代码写出来,注意加粗的部分

privatedelegatevoidMaxProcessBarEventHandle();//声明最大化客户端进度条控件方法的委托

privatevoidOnWebMethodCompleted(IAsyncResultp_AsyncResult)

{

Service1service1
=newService1();

Class1result
=service1.EndGetClass1(p_AsyncResult);

MessageBox.Show(
"IDis"+(result.ID.ToString()+",Nameis"+result.Name.ToString()));

this.Invoke(newMaxProcessBarEventHandle(MaxProcessBar));//从进度条创建的线程安全调用MaxProcessBar方法

}



privatevoidMaxProcessBar()

{

//客户端进度条最大化方法


progressBar1.Value
=progressBar1.Maximum;

}

分享到:
评论

相关推荐

    超级有影响力霸气的Java面试题大全文档

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 20、abstract class和interface有什么区别? ...

    asp.net知识库

    NET2.0系列介绍(一).NET 2.0 中Web 应用程序主题的切换 ASP.NET 2.0 中Web 应用程序主题的切换 2.0正式版中callback的一些变化+使用示例(ASP.NET 2.0) Server Side ViewState 在服务器端存贮ViewState (ASP.NET...

    java 面试题 总结

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 17、abstract class和interface有什么区别? 声明方法...

    亮剑.NET深入体验与实战精要2

    7.8 实现异步调用Web Service 297 7.9 如何保证Web Service的安全 299 7.9.1 通过SoapHeader来增强 Web Service的安全性 299 7.9.2 采用SSL实现加密传输 302 7.9.3 访问IP限制 315 7.10 Web Service开发中需要注意的...

    亮剑.NET深入体验与实战精要3

    7.8 实现异步调用Web Service 297 7.9 如何保证Web Service的安全 299 7.9.1 通过SoapHeader来增强 Web Service的安全性 299 7.9.2 采用SSL实现加密传输 302 7.9.3 访问IP限制 315 7.10 Web Service开发中需要注意的...

    C#微软培训资料

    18.2 在 C #代码中调用 C++和 VB 编写的组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...

    java面试宝典

    70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? 17 72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73...

    ABAP面试大全

    2.2.3 SAP中有几种表,他们的区别是什么? 10 2.2.4什么是簇表(cluster table)?举出知道的簇表。 10 2.2.5找数据库表,有哪些常用的方法。 10 2.2.6如何建立数据库锁对象,激活锁对象产生的Function Module的名字...

    千方百计笔试题大全

    70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? 17 72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73...

    java面试题

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步。在很多情况下采用异步往往更有效率。 数据库三大范式? 答:1:确保每列都是不可分割的原子值 2...

    ASP.NET3.5典型模块开发源代码

    24.2.2 在程序中使用Web Service 330 24.3 小结 332 第25章 在线随机考试模块 333 25.1 随机考试的技术要点 333 25.1.1 随机性 333 25.1.2 防止重复 334 25.2 考题数据库设计 334 25.2.1 设计数据库...

    java基础题 很全面

    54. java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 13 55. java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类? 14 56....

    Java面试宝典2010版

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 47、sleep() 和 wait() 有什么区别? 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明。 ...

    最新Java面试宝典pdf版

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...

    Java面试笔试资料大全

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...

    Java面试宝典-经典

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...

    JAVA面试宝典2010

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...

    java面试题大全(2012版)

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...

    Java面试宝典2012版

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例...

    java面试宝典2012

    46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 32 47、sleep() 和 wait() 有什么区别? 33 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...

Global site tag (gtag.js) - Google Analytics