如何使用异步调用

news/2024/7/4 8:23:36

下面一段文字从别处引用:

BeginInvoke方法用于启动异步调用。它与需要异步执行的方法具有相同的参数。此外,它还有两个可选参数。第一个参数是一个AsyncCallback委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递数据。BeginInvoke立即返回,不会等待异步调用完成,被调用的方法将在线程池线程中执行。因此,提交请求的原始线程与执行异步方法的线程池线程是并行执行的。BeginInvoke会返回一个IAsyncResult对象,可以使用该对象来监视异步调用进度,也可将该对象传递给EndInvoke方法,以获取异步执行的方法的返回值。

EndInvoke方法用于检索异步调用的结果。调用BeginInvoke方法后可随时调用EndInvoke方法;如果异步调用尚未完成,EndInvoke方法将一直阻塞调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke方法的参数包括需要异步执行的方法的out和ref参数,以及由BeginInvoke返回的IAsyncResult对象。因此,通过EndInvoke方法可以获得异步调用的方法的所有输出数据,包括返回值、out和ref参数。

AsyncCallback委托表示在异步操作完成时调用的回调方法,其定义如下:

public delegate void AsyncCallback(IAsyncResult ar);

一、下面是一个简单的例子:

public class Test
    {
        private int WorkerFunction(string a, string b)
        {
            //this is the guy that is supposed to do the long running work 
            Console.WriteLine(a);
            Console.WriteLine(b);
            return a.Length + b.Length;
        }

        private void MyCallBack(IAsyncResult ar)
        {
            var function = ar.AsyncState as Func<string, string, int>;
            int result = function.EndInvoke(ar);

            Thread.Sleep(1000);
            Console.WriteLine("Result is {0}", result);
        }
        public void CallMethod()
        {
            var function = new Func<string, string, int>(WorkerFunction);
            IAsyncResult result = function.BeginInvoke("param1", "param2", MyCallBack, function);
            //function.BeginInvoke("param1", "param2", MyCallBack, function);
            Console.WriteLine(" Finished begin invode.");
        }
    }
CallMethod()方法中首先定义了一个委托function,再用委托实现异步调用:
IAsyncResult result = function.BeginInvoke("param1", "param2", MyCallBack, function);
BeginInvoke方法有四个参数:
1.前两个是传递给被委托的方法WorkerFunciton(string p1, string p2)
2. 第三个参数MyCallBack是一个回调函数,在异步委托方法执行完成之后,会调用该回调方法。
  public delegate void MyCallBack(IAsyncResult ar);

IAsyncResult接口定义了四个公开属性,通过它们可以获取异步调用的状态。

—  AsyncState:获取用户定义的对象,它限定或包含关于异步操作的信息。

—  AsyncWaitHandle:获取用于等待异步操作完成的 WaitHandle。

—  CompletedSynchronously:获取异步操作是否同步完成的指示。

—  IsCompleted:获取异步操作是否已完成的指示。

3. 第四个参数function 是用于传递数据给回调函数。传递给MyCallBack的对象function存储在参数ar.AsyncState中。在callBack 函数中使用这个传回的对象前需要先将其转换为function的类型。
    var function = ar.AsyncState as Func<string, string, int>;
最后再回调函数中使用EndInvoke(ar)方法结束异步线程的使用。
当只需要实现异步调用,而不关心异步调用状态(什么时候结束)时,可以不用给出回调函数,直接用null替代即可,如下:
function.BeginInvoke("param1", "param2", Null, Null);

二、在socket client 程序中,经常需要连接server端,下面是一个异步连接server的实例,包括server端的连接,数据发送:
public class Client
    {
        private readonly string _hostname;
        private readonly int _port;
        private TcpClient _client;
        private NetworkStream _networkStream;

        private const int BufferSize = 4096;
        private readonly byte[] _buffer = new byte[BufferSize];

        public delegate void OnConnectedDelegate();
        public delegate void OnDataSentDelegate(string msg);
        public delegate void OnDataRecvDelegate(string msg);
        public delegate void OnClosedDelegate();

        public OnConnectedDelegate OnConnected;
        public OnClosedDelegate OnClosed;
        public OnDataSentDelegate OnDataSent;
        public OnDataRecvDelegate OnDataRecv;

        public Client(string hostname, int port)
        {
            if (string.IsNullOrEmpty(hostname) || port <= 0)
                throw new ArgumentException("Invalid IPAddress.");

            _hostname = hostname;
            _port = port;
        }

        public void Connect()
        {
            if (_client == null)
            {
                try
                {
                    _client = new TcpClient();

                    _client.BeginConnect(_hostname, _port, OnConnectedCallback, null);
                }
                catch (Exception ex)
                {
                    Logger.ErrorWithFormat("Failed to connect to {0}:{1}. {2}", _hostname, _port, ex.Message);

                    Close();
                }
            }
        }

        private void OnConnectedCallback(IAsyncResult ar)
        {
            try
            {
                _client.EndConnect(ar);

                _networkStream = _client.GetStream();

                if (OnConnected != null)
                    OnConnected();
            }
            catch (Exception ex)
            {
                Logger.ErrorWithFormat("Failed to connect to {0}:{1}. {2}", _hostname, _port, ex.Message);

                Close();
            }
        }

        public void Send(string msg)
        {
            if (string.IsNullOrEmpty(msg))
                return;

            byte[] bytes = Encoding.UTF8.GetBytes(msg);
            Send(bytes);
        }

        public void Send(byte[] bytes)
        {
            if (null == bytes)
                return;

            if (_networkStream != null)
            {
                try
                {
                    var msg = Encoding.UTF8.GetString(bytes);
                    _networkStream.BeginWrite(bytes, 0, bytes.Length, SendCallback, msg);
                }
                catch (Exception ex)
                {
                    Logger.ErrorWithFormat("Failed to send {0} bytes. {1}", bytes.Length, ex.Message);

                    Close();
                }
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            if (_networkStream != null)
            {
                try
                {
                    _networkStream.EndWrite(ar);

                    var msg = ar.AsyncState as string;
                    Logger.InfoWithFormat(" >> Sent msg : {0}", msg);

                    if (OnDataSent != null)
                    {
                        OnDataSent(msg);
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorWithFormat("Failed to sent to {0}:{1}. {2}", _hostname, _port, ex.Message);

                    Close();
                }
            }
        }

        public void Read()
        {
            if (_networkStream != null)
            {
                try
                {
                    _networkStream.BeginRead(_buffer, 0, _buffer.Length, ReadCallback, null);
                }
                catch (Exception ex)
                {
                    Logger.ErrorWithFormat("Failed to read message. {0}", ex.Message);

                    Close();
                }
            }
        }

        private void ReadCallback(IAsyncResult ar)
        {
            if (_networkStream != null)
            {
                try
                {  
                    var bytesRead = _networkStream.EndRead(ar);
                    if (bytesRead > 0)
                    {
                        var msg = Encoding.UTF8.GetString(_buffer, 0, bytesRead);

                        Logger.InfoWithFormat(" >> Read msg : {0}", msg);

                        if (OnDataRecv != null)
                        {
                            OnDataRecv(msg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorWithFormat("Failed to read to {0}:{1}. {2}", _hostname, _port, ex.Message);

                    Close();
                }
            }
        }

        public void Close()
        {
            if (_networkStream != null)
            {
                _networkStream.Close();
                _networkStream = null;
            }

            if (_client != null)
            {
                _client.Close();
                _client = null;
            }

            if (OnClosed != null)
            {
                OnClosed();
            }
        }
    }
 
 

  

 
 
 

 

 

 

转载于:https://www.cnblogs.com/moon-sunshine/archive/2013/05/23/3093944.html


http://www.niftyadmin.cn/n/3311926.html

相关文章

Protocol Buffer(语言规范)

该系列Blog的内容主体主要源自于Protocol Buffer的官方文档&#xff0c;而代码示例则抽取于当前正在开发的一个公司内部项目的Demo。这样做的目的主要在于不仅可以保持Google文档的良好风格和系统性&#xff0c;同时再结合一些比较实用和通用的用例&#xff0c;这样就更加便于公…

php5 session丢失,关于php5 session 丢失问题

关于php5 session 丢失问题php5 session丢失的解决办法&#xff1a;1、修改“php.ini”配置文件&#xff1b;2、使用“Fecade Session::get()”获取或使用助手函数“session()”&#xff1b;3、重启服务&#xff0c;清除缓存。推荐&#xff1a;《PHP视频教程》think PHP5.1使用…

使用snmp4j监听和发送消息

MultiThreadedTrapReceiver类&#xff1a;用于接收trap消息 Java代码 package com.snmp.trap; import java.io.IOException; import java.net.UnknownHostException; import java.util.Vector; import org.snmp4j.CommandResponder; import org.snmp4j.CommandRespon…

搭建C++编译环境

2019独角兽企业重金招聘Python工程师标准>>> 安装git&#xff0c;g gcc 并且升级到4.9版本&#xff0c;用premake 从vs工程 输出为makefile 等 --安装git sudo add-apt-repository ppa:git-core/ppa sudo apt-get update sudo apt-get install git --安装g sudo ap…

php 登陆程序,PHP(10) 用户登录程序(版本2)

用户登录程序(版本2)今天&#xff0c;我们把我们上一篇博文中的小项目做一个升级版本&#xff01;1、产生彩色的验证码在上一篇文中&#xff0c;我们产生了随机的验证码&#xff0c;但是我们在有的网站上看到的验证码是彩色的&#xff0c;那么&#xff0c;我们怎么来产生彩色的…

【语言处理与Python】3.5正则表达式的有益作用

提取字符块 #找到所有的无重叠的匹配指定的正则表达式re.findall(r’[aeiou]’,word)#看看一些文本中的两个或者两个以上的元音序列&#xff0c;并确定他们的相对频率wsfsorted((set(nltk.corpus.treebank.words()))fdnltk.FreqDist(vs for word in wsjfor vs in re.findall(r’…

yiic.php,执行yiic命令提示’php.exe’将YII添加到系统环境变量

还有个问题就是每次执行yiic命令时要把yiic的全路径打出来才行,比如我的yii框架在F:\myproject里面,我每次执行的时候都要F:\myproject\yii\framework\yiic webapp yiiblog我们可以把yiic也加入系统环境变量,加入以下代码:假如php.exe这个目录在E:\Server\phpF:\myproject\yii\…

cvs和svn的区别

1> cvs是不支持文件的复制 移动和重命名 而svn支持 2> cvs在网络中断等时 提交的部分文件也会生效 而svn当用户全部提交完变更的文件时 才会生效 否则直接回滚 变成最初状态 3> 版本控制上 对于一个文件foo.c 在cvs1.1 版本和1.2版本始终是不相同的 而svn中有可能相…