如何实现webservice的异步调用

如何实现webservice的异步调用,第1张

对异步调用的理解:

说白了异步调用其实就是调用者线程和执行被调用过程的线程并行执行。

实现WEB服务方法异步调用有不同方法都可以实现,下面给你举三个例子:

第一种方法是:使用回调

使用这种方式来进行WEB服务方法的异步调用关键是在启动异步调用时传入一个代理实例作为调用结束时的回调方法。这样用以回调的方法调用结束异步调用的方法获得异步调用的结果。若调用方要跟异步调用同步,则需要在启动异步调用时传入一个同步对象[作为最后一个参数],然后在回调方法中通过IAsyncResult的AsyncState成员获得该对象。

举一个例子:

假如有下面一个WEB服务方法

[webmethod]

public string GetName(string name)

{return name}

/*****************客户端调用**************************

class Client

{

localhost1.Serivice service=new localhost1.Service()

public void GetResults(IAsyncResult ar)

{

MannualResetEvent ent

ent=(MannualResetEvent)ar.AsyncState

string ret=service.EndGetName(ar)

Console.WriteLine("the result is:"+ret)

ent.Set()

}

public void CallWithBack()

{

string name="kim"

AsyncCallBack callBack

callBack=new AsyncCallBack(GetResults)

MannualResetEvent ent=MannualResetEvent(false)

service.BeginGetName(name,callBack,ent)

//做其他的事情

ent.WaitOne()

}

static void Main(string[] ars)

{

CallWithBack()

}

}

第二种方法使用轮询

轮询就是不断检查异步调用启动后获得的IasyncResult变量的IsCompleted属性,以等待异步调用结束。而一般在判断异步调用还未结束时,调用Thread类的静态方法Sleep(0)迫使当前线程由运行状态转入就绪状态。

如:

WEB服务方法还是以上面的例子为例:

客户端实现:

Class Client

{

localhost1.Serivice service=new localhost1.Service()

public void CallWithQuery()

{

string name="kim"

IasyncResult ar

ar=service.BeginGetName(name,null,null)

while(!ar.IsCompleted)

{

//做其他事情

Console.WritleLine("Watting....")

Tread.Sleep(0)

}

string ret

ret=service.EndGetName(ar)

Console.WriteLine("the result is:"+ret)

}

static void Main(string[] ars)

{

CallWithQuery()

}

}

第三种方法是:开始调用,结束调用

这种方式在启动异步调用后用结束异步调用的方式获取结果,如果异步调用没有结束,当前线成被阻塞。

如:

WEB服务方法还是以上面的例子为例:

客户端实现:

Class Client

{

localhost1.Serivice service=new localhost1.Service()

public void CallWithEnd()

{

string name="kim"

IasyncResult ar=service.BeginGetName(name,null,null)

string ret=service.EndGetName(ar)

Console.WriteLine("the result is:"+ret)

}

static void Main(string[] ars)

{

CallWithEnd()

}

}

这样的写法有点问题:

1)服务器端既然采用了异步方式Accept,就没有必要再启线程

2)估计allDone是一个ManualResetEvent。用ManualResetEvent的目的什么呢?

服务器端采用异步Accept的代码其实很简单,也不需要ManualResetEvent同步

   public class AppTCPServer

    {

        public AppTCPServer(string localIP, int port)

        {

            Socket socket = new Socket(AddressFamily.InterNetwork, 

                                                        SocketType.Stream, 

                                                        ProtocolType.Tcp)

            EndPoint localEP = new IPEndPoint(IPAddress.Parse(localIP), port)

            socket.Bind(localEP)

            socket.Listen(100)

            socket.BeginAccept(AcceptAsync, socket)

        }

        private void AcceptAsync(IAsyncResult ar)

        {

            Socket socket = ar.AsyncState as Socket

            try

            {

                Socket client = socket.EndAccept(ar)

                Console.WriteLine("客户端连接成功!客户端:{0}", client.RemoteEndPoint.ToString())

                if (OnConnected != null)

                {

                    OnConnected(this, new ClientConnectedEventArgs(client))

                }

            }

            catch (Exception e)

            {

                Console.WriteLine("AcceptAsync发生异常,异常信息:\n{0}", e.Message)

            }

            finally

            {

                //继续异步Accept

                socket.BeginAccept(AcceptAsync, socket)

            }

        }

        //客户端连接后的事件 OnConnect

        public event EventHandler<ClientConnectedEventArgs> OnConnected

    }

    /// <summary>

    /// 事件参数:接收客户端连接后的事件参数

    /// </summary>

    public class ClientConnectedEventArgs : EventArgs

    {

        public ClientConnectedEventArgs(Socket clientSocket)

        {

            ClientSocket = clientSocket

        }

        public Socket ClientSocket { get private set }

    }

    

    class Program

    {

        static void Main(string[] args)

        {

            AppTCPServer server = new AppTCPServer("127.0.0.01", 8000)

            server.OnConnected += server_OnConnected

            Console.WriteLine("按任意键结束程序……")

            Console.ReadKey()

        }

        static void server_OnConnected(object sender, ClientConnectedEventArgs e)

        {

            Socket client = e.ClientSocket

            string hello = "Hello from AppTCPServer"

            client.Send(Encoding.Default.GetBytes(hello))

        }

    }

客户端测试程序

   class Program

    {

        static void Main(string[] args)

        {

            //模拟100个客户连接服务器

            for (int i = 0 i < 100 i++)

            {

                Socket socket = ConnectToServer("127.0.0.1", 8000)

                byte[] buffer = new byte[1024]

                int bytesRecevied = socket.Receive(buffer, buffer.Length, SocketFlags.None)

                byte[] messageBytes = new byte[bytesRecevied]

                Array.Copy(buffer, messageBytes, bytesRecevied)

                Console.WriteLine(Encoding.Default.GetString(messageBytes))

                socket.Disconnect(false)

                socket.Close()

            }

            Console.ReadKey()

        static Socket ConnectToServer(string serverIP, int serverPort)

        {

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

            EndPoint localEP = new IPEndPoint(IPAddress.Any, 0)

            socket.Bind(localEP)

            socket.Connect(new IPEndPoint(IPAddress.Parse(serverIP), serverPort))

            return socket

        }

    }

异步就是在发生某件事的时候 “自动” 开一个线程去调用注册的委托。所以,你这个问题分2种情况。

一:事件已发生,另一个线程已开启,这种情况,中止异步可以中止当前线程(Thread.CurrentThread.Abort()),也可以直接return退出那个委托啊魂淡!

二:事件未发生,线程还未开启,这种情况下...你想结束什么?直接关掉那个异步对象不就是了!


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11446661.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-16
下一篇2023-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存