蛙蛙推荐:如何编写异步的WebService(不是异步调用WebService)

本文介绍如何在.NET中实现异步WebService,通过使用BeginXXX/EndXXX方法对WebService进行异步处理,提高服务吞吐量。文章提供了具体实现步骤与代码示例。

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

如何编写异步的WebService(不是异步调用WebService)

摘要:我们做webService的时候,如果在处理用户请求的时候需要进行异步IO操作,在异步IO完成前会有一个线程在那里同步等待,正在等待的请求太多的话会大大降低服务的吞吐量,asp.net2.0里有异步的HttpHandler能解决这个问题,可.net2.0没给弄一个异步的webservice,这就需要我们自己去实现了。

分析:.net处理webservice请求大致是这样的
1、用SyncSessionlessHandler来接收客户端的soap请求;
2、把这些文本的xml构建SoapMessage,SoapMessage里包含SoapMethod及参数等信息。
3、根据uri来获取请求的是哪个WebService,然后用反射取出该WebService里包含WebMethodAttriube的方法。
4、用SoapMessage里信息和反射出来的MethodInfo去匹配,并用反射的方式去Invoke Webservice那个类的方法。
5、把那个方法返回的值再序列化成Soap格式返回给客户端。

当然只是大致分析,具体的处理还包含是否启用事务,是否启用Session,以及大量的请求验证,缓存反射信息等操作。

在客户端异步调用web服务端时候会使用AsyncSessionHandler和AsyncSessionlessHandler这两个异步httphandler,但如果客户端同步调用就不能使用了。

知道了原理之后,我们可以写一个异步httphandler,获取用户请求构建SoapMessage,获取参数信息后,去调用自己指定的方法,而不是默认要调用的方法,在我们指定的方法里发送异步IO请求,在异步IO完成后,我们再构建原来方法的返回值,序列化成Soap格式,返回给客户端,然后设置异步httphandler的IAsyncResult.IsCompleted为true。

具体的部分我已经封装好了,下面介绍一下步骤。
1、先设计好webservice,如下

using  System;
using  System.Web.Services;

namespace  TestWS
{
    
public   class  UserInfo
    {
        
public   int  Age;
        
public  DateTime Birthday;
        
public   string  Password;
        
public   bool  Sex;
        
public   string  Username;
    }

    
public   class  RegisterResult
    {
        
public   string  Description;
        
public   int  StatusCode;
        
public   string  Username;
    }

    [WebService(Namespace 
=   " http://www.fetionmm.com/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
    
public   class  Service1 : WebService
    {
        [WebMethod]
        
public  RegisterResult RegisterUser(UserInfo userInfo)
        {
            var result 
=   new  RegisterResult();
            result.Username 
=  userInfo.Username;
            result.StatusCode 
=   200 ;
            result.Description 
=   " ok " ;
            
return  result;
        }
    }
}

2、写一个ashx文件,如下

using  MySoapLib;

namespace  TestWS
{
    
// 这个类要继承自SoapAsyncHandler,它会自动接收soap消息并调用匹配的方法
    
// 然后要编写和VirtualServiceUri所指向的webService有相同的方法,但返回值都是void,
    
// 在对请求处理完成时构造返回值,再调用asynch.WriteResult来向调用者返回SOAP消息
     public   class  Handler1 : SoapAsyncHandler
    {
        
protected   override   string  VirtualServiceUri
        {
            
get  {  return   " /Service1.asmx " ; }
        }

        
public   void  RegisterUser(UserInfo userInfo)
        {
            var result 
=   new  RegisterResult();
            result.Username 
=  userInfo.Username;
            result.StatusCode 
=   200 ;
            result.Description 
=   " ok " ;
            asynch.WriteResult(result);
        }
    }
}

3、编写调用者,设置代理类的uri为新的ashx,而不是默认的asmx,如下

using  System;
using  WSClient.localhost;

namespace  WSClient
{
    
internal   class  Program
    {
        
private   static   void  Main( string [] args)
        {
            Console.WriteLine(
" start " );
            var service1 
=   new  Service1();
            service1.Url 
=   " http://localhost:10514/Handler1.ashx " ;
            var userInfo 
=   new  UserInfo();
            userInfo.Username 
=   " onlytiancai " ;
            userInfo.Password 
=   " password " ;
            userInfo.Age 
=   25 ;
            userInfo.Birthday 
=  DateTime.Parse( " 1983-01-01 " );
            userInfo.Sex 
=   false ;
            RegisterResult result 
=  service1.RegisterUser(userInfo);
            Console.Write(
" name:{0},status:{1},desc,{2} " , result.Username,
                          result.StatusCode, result.Description);
            Console.ReadKey();
        }
    }
}

具体的原理,大家看看代码吧,再挑挑毛病。

代码下载:

http://files.cnblogs.com/onlytiancai/AsyncWebService.zip

 

此文撤回,原来实现服务端的异步web服务有官方方法,我先去吃饭,回来再试试,汗了,白浪费哥们呕心沥血几十载把代码扣出来了。

http://www.microsoft.com/india/msdn/events/Inside%20ASP.NET%20Runtime.zip_

http://fhict.fontys.nl/Deeltijd/1JarigeStudies/CSA/Lesmateriaal/Week%202/Achtergrond/WebServicesTutorial.ppt

 

Server-Side Asynchronous Calls

         Can implement asynchronous design patterns in your Web service

                   Asynchronous Web method pattern

                   Custom pattern      

         Mitigate risk of operation timeout

         Perform lengthy operations on a different thread

         Client proxy usage doesn’t change

 

Asynchronous Web Methods

         WebServiceHandlerFactory

                   Default IHttpHandlerFactory assigned to process Web service extensions (*.asmx)

                   Uses reflection to determine if method to invoke is implemented synchronously or not

                   Returns appropriate IHttpHandler object to process the Web method request

 

Web Service Handlers

         System.Web.Services.Protocols

                   Contains (undocumented) handlers

                   Functionality varies based on session and asynchronous method implementation

         Handlers:

                   SyncSessionHandler

                   AsyncSessionHandler

                   SyncSessionlessHandler

                   AsyncSessionlessHandler

 

BeginXXX()/EndXXX() Methods

         Replace single Web method with asynchronous method pair

         Follow asynchronous design pattern for method signatures

 

         [WebMethod]

         public IAsyncResult BeginSleeper2(int mm, AsyncCallback cb, object state)

         {...}

        

         [WebMethod]

         public string EndSleeper2(IAsyncResult ar)

         {...}

 

         WSDL still exposes a single method for the pair

         Framework handles invocation of asynchronous methods

                   Frees service thread to handle other requests

                   EndXXX() is invoked by handler when framework receives callback

 

Custom Asynchronous Pattern

         Implement complex server-side threading behaviors

         Provide methods to query status and request results

         Provide storage of results for transmission on request

 

测试通过,我汗死。

using  System;
using  System.Web.Services;

namespace  TestWS
{
    [WebService(Namespace 
=   " http://www.fetionmm.com/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
    
public   class  Service1 : WebService
    {
      
        [WebMethod]
        
public  IAsyncResult BeginRegisterUser(UserInfo userInfo,AsyncCallback cb,  object  state)
        {
            RegisterUserDeleate d 
=  RegisterUser;
            
return  d.BeginInvoke(userInfo, cb, d);
        }

        
private   delegate  RegisterResult RegisterUserDeleate(UserInfo userInfo);
        
public  RegisterResult RegisterUser(UserInfo userInfo) {
            RegisterResult result 
=   new  RegisterResult();
            result.Username 
=  userInfo.Username;
            result.StatusCode 
=   200 ;
            result.Description 
=   " ok " ;
            
return  result;
        }

          [WebMethod]
        
public  RegisterResult EndRegisterUser(IAsyncResult ar)
          {
              RegisterUserDeleate d 
=  ar.AsyncState  as  RegisterUserDeleate;
              
return  d.EndInvoke(ar);
          }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值