WebService异步
异步是一个庞大的话题,但总的来说,我认为它有不阻塞当前请求线程、提高吞吐量等作用。
对于服务端和客户端互相调用的程序,我认为异步可以分为客户端异步、服务端异步,并且他们异步操作互不影响。
从是否等待来看,我觉得可以分为等待异步方式和不等待的异步方式。
异步代码编写上,主要有两种方式:APM Asynchronouse Programming Model,EAP Event-base Asynchronous Pattern。它们分别是BeginXXX,EndXXX和基于事件的XXXCompleted,XXXAsync的异步方式。
除了创建线程等方式的异步,如果和CPU并行执行任务,是需要硬件支持的,大多硬件都提供了DMA功能,当硬件在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再用中断的方式反馈给CPU,这块更专业的解释需要参考其他文章资料。封装后对于.net程序的异步,一般都是通过回调的方式通知异步完成了。
WebService异步
我认为WebService客户端异步主要包括如下:
1、 用线程Thread直接开子线程,可以和主调用线程异步执行。
2、 用线程池ThreadPool开后台线程,和主调用线程异步执行。
3、 Begin[WebMethodName]异步调用,End[WebMethodName]方式回调。
4、 [WebMethodName]Completed+=委托回调,[WebMethodName]Async异步方式调用。
对于winform程序,常用的还有BackgroundWorker组件来异步执行任务。
WebService服务端异步主要包括如下:
1、 配置webmethod为One-way方式,即在WebMethod添加属性为:
[System.Web.Services.Protocols.SoapDocumentMethod(OneWay = true)],对于One-way方式,服务端要求是void返回类型,客户端调用后就不关心后续执行是否正确或异常了,直接返回客户端,因此我自己认为可以算服务端配置的一个异步。但经过我的测试,发现One-way方式始终要增加一个windows线程来处理,并且这个线程为1个工作线程,因此最好不要大量使用。
2、 Begin[WebMethodName],End[WebMethodName]方式,服务端配置和客户端配置不一样,服务端配置BeginXXX,EndXXX方式,BeginXXX返回IAsyncReSult结果,EndXXX接受IAsyncResult为参数的方法,对于客户端,同样需要等待服务端的整个执行流程,唯一的优化是在BeginXXX和EndXXX之间释放出了一个CLR线程,可以提高并发量。对于回调函数EndXXX,它会根据不同情况占据不同的CLR线程。
3、 服务端自己开子线程,可以立即返回客户段,也可以用信号量等待服务端执行完毕再返回,或者插入消息队列等,异步逻辑,因此我觉得泛指的异步是一个大的话题。
WebService引用方式
对于.Net引用webserv ice主要有两种方式:
1、 Web引用
在.net2.0框架下的项目,右键项目,下面即有添加Web引用,如果是高版本框架项目下,在添加服务引用下,进入高级按钮选项,有添加Web引用的按钮。如图:
图一
实际它内部是通过WSDL.exe程序来引用webservice,但它只能生成基于事件的异步方式,执行命令比如:
wsdl.exe http://localhost:4003/Service1.asmx /out:Service1.cs,执行后如:

图二
2、 服务引用
它内部通过SvcUtil.exe程序,引用.net2.0后新增的WCF等,兼容以前web服务,比如:
svcutil http://localhost:4003/Service1.asmx /out:service2.cs,执行后如:

图三
WSDL和SvcUtil程序位于C:\Program Files\Microsoft SDKs\Windows\v6.0A(可能其他版本)\bin目录下,生成了cs文件后,可以通过:
csc.exe /target:library /out:Service1.dll Service1.cs 来生成对应的dll文件。
但是默认服务引用不会生成异步调用方式,需要在高级里勾选生成异步操作,它会生成基于事件和APM的异步调用方式,如图:

图四
异步示例
下面贴下服务端异步方式的示例代码:
[WebMethod]
public IAsyncResult BeginServerAsyncHelloWorld(string str, AsyncCallback cb, object state)
{
//http://lawson.cnblogs.com
string connectionString = @"Data Source=localhost;User ID=sa;Password=1123;Asynchronous Processing=true";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
IAsyncResult ir = command.BeginExecuteReader(cb, command, System.Data.CommandBehavior.CloseConnection);
return ir;
}
[WebMethod]
public string EndServerAsyncHelloWorld(IAsyncResult ir)
{
StringBuilder sb = new StringBuilder();
SqlCommand command = (SqlCommand)ir.AsyncState;
省略后面代码,这里看到BeginXXX和EndXXX属性方法字段都有制定格式,比如begin里后面两个为:AsyncCallback cb, object state,分别为回调函数和主调函数和回调函数之间的传地址,比如这里传递的是SqlCommand。并且对于客户端,它发现的方法只为ServerAsyncHelloWorld了。
从上面代码可以看出,WebService服务端异步只是一个壳子,具体怎么异步还需要内部的内容执行异步调用。如果WebMethod不标注为异步调用方式,内部调用异步代码,实际请求会消耗更多的CLR线程来执行异步,或造成请求线程的阻塞等待。
对于回调函数,比如ADO.NET操作它会占用1个工作线程,但对于委托异步Remoting等会占用1个IO线程,如需要对线程更好控制的情境,需要注意这些地方。
虽然服务端用了异步方式,对于客户端,同样可以再继续异步,它们互不影响,比如可以用基于事件异步,或APM方式的异步调用服务端异步方法。
最后,对于WebService服务端异步方式,服务端可以操作基于IOCP的异步调用方式,异步过程中节约线程,提供并发量。对于客户端异步方式,可以不阻塞主线程,提高用户体现等。
本文是自己对WebService异步的一些总结,如有不对,欢迎指正。
标签:
Webservice
, 异步
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探