[转]web service实现原理与异步调用

net2.0环境下,Web service中的每个方法,在Client端添加引用后生成的代理类中都会产生相应的异步方法和结束事件。我们可以利用这个异步方法和事件,轻松实现异步调用web service.

    简单范例

    假设在web service中定义了一个数据查询的方法:

[WebMethod]
   public DataSet ExecuteQuery(string SQL)
        {
            using (OracleConnection conn = new OracleConnection(connstrSQL))
            {
                try
                {
                    conn.Open();
                    OracleCommand cmd = new OracleCommand(sql,conn);
                    OracleDataAdapter ada = new OracleDataAdapter(cmd);
                    DataSet ds = new DataSet();
                    ada.Fill(ds);
                    return ds;
                }
                catch (OracleException ex)
                {
                    throw new Exception(ex.Message);
                }
                finally
                {
                    conn.Close();
                }
        }
    客户端:

///说明:
///panel1中放置了动态加载字样的图片等
///  
public partial class frmStock : Form
    {
        Service.MyService w = new Service.MyService(); //调用web service
        public frmStock()
        {
            InitializeComponent();
        }
        private void frmStock_Load(object sender, EventArgs e)
        {
            //添加异步方法执行后触发事件
            w.ExecuteQueryCompleted += new WMS.ExecuteQueryCompletedEventHandler(w_ExecuteQueryCompleted);
        }
        private void btnFind_Click(object sender, EventArgs e)
        {
            string sql = "select * from test";
             w.ExecuteQueryAsync(sql);  //调用对应异步方法
             ChangeStatus(true);
        }
        void w_ExecuteQueryCompleted(object sender, WMS.ExecuteQueryCompletedEventArgs e)
        {
           DataTable dt= e.Result.Tables[0];  //获得执行结果 e
           ChangeStatus(false);
           if (dt.Rows.Count <= 0)
           {
               MessageBox.Show("没有数据", "information", MessageBoxButtons.OK, MessageBoxIcon.Information);
               return;
           }
           gvshow.AutoGenerateColumns = false;
           gvshow.DataSource = dt;
        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void ChangeStatus(bool sign)
        {
            panel1.Visible = sign;
        }
    }
   这样,可以

    1.避免了假死现象

    2.可以提供友好的用户体验

    实现原理

    web service 发布后,客户端添加引用,之后vs实际上在此时已经在后台生成本地代理类。之后看起来像是对web service的操作,实际上是对本地代理类的操作。代理类中处理网路访问逻辑,客户端的使用就象操作本地类一样简单便捷。

    客户端发出web service请求后,请求到达代理类,代理类处理请求从服务端获得SOAP数据包,而后进行数据处理后转发客户端。此中间涉及到的关于SOAP,WSDL等定义,简单的可以理解为:SOAP中定义了传输数据类型的格式和规则,而WSDL则以XML的形式定义了web service的消息和有关操作,通过http传输协议进行数据传输...

    那么代理类中到底如何定义的呢?

    我们可以通过自定义代理类的方式来分析代理类的详细信息。

    1.首先创建web service:Service.asmx

    2.IIS中建立虚拟目录并发布

    3.通过WSDL.exe工具生成代理类。

    打开SDK命令提示窗口,如下作业:

d:\Program Files\Microsoft Visual Studio 8\SDK\v2.0>wsdl http://localhost/Serve/Service.asmx?wsdl
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'd:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Service.cs'.

    其中service.cs就是生成的代理类,打开可见,其中涉及到异步方法,事件的生成。(部分代码如下)

/// <remarks/>
    public event HelloWorldCompletedEventHandler HelloWorldCompleted;
    /// <remarks/>
    public event showInfoCompletedEventHandler showInfoCompleted;
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    public string HelloWorld() {
        object[] results = this.Invoke("HelloWorld", new object[0]);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginHelloWorld(System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("HelloWorld", new object[0], callback, asyncState);
    }
    /// <remarks/>
    public string EndHelloWorld(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void HelloWorldAsync() {
        this.HelloWorldAsync(null);
    }
    /// <remarks/>
    public void HelloWorldAsync(object userState) {
        if ((this.HelloWorldOperationCompleted == null)) {
            this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);
        }
        this.InvokeAsync("HelloWorld", new object[0], this.HelloWorldOperationCompleted, userState);
    }
    private void OnHelloWorldOperationCompleted(object arg) {
        if ((this.HelloWorldCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.HelloWorldCompleted(this, new HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    4.通过csc命令把service.cs生成为dll文件

    5.在专案中添加对此dll的引用

    6.这样对此dll的应用实际上就是通过这个代理类访问我们发布的web service.

    设计模式的应用

    此种方式的实现,在设计模式中就是有名的“代理模式”的实现方式。

原作者:http://blog.csdn.net/JustLovePro/archive/2008/08/27/2836898.aspx

原文地址:https://www.cnblogs.com/iwaitu/p/1690086.html