zoukankan      html  css  js  c++  java
  • C#IAsyncResult异步回调函数的解释

    问题:IAsyncResult ar 是如何通过ar.AsyncState强制转换成TCPClientState类型

    :实例中使用的方法如下

    我给IAsyncResult ar传入了TCPClientState 类型的参数。简单来说:传入什么类型,转换时就需要什么类型。

    TCPClientState state = (TCPClientState)ar.AsyncState;

    IAsyncResult 传递的类型属于一个object 抽象类型

    IAsyncResult 类型是非常严格的,有着非常明确的属性和方法。

    但是其 AsyncState 属性不过就是一个最简单的 object 引用,把调用异步方法的你的代码所传送的对象参数给“读取”出来。

    原因:.net framework的设计者不知道你要传递什么方法,而且那是2000年设计的功能,那时候也没有什么泛型,因此设计者给 IAsyncResult 类型设计了一个 object 类型的属性,让你用来传递参数。

    代码方便理解

    IAsyncResult 部分代码:

    #region 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    // C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.0mscorlib.dll
    #endregion
    
    using System.Runtime.InteropServices;
    using System.Threading;
    
    namespace System
    {
        //
        // 摘要:
        //     表示异步操作的状态。
        [ComVisible(true)]
        public interface IAsyncResult
        {
            //
            // 摘要:
            //     获取用户定义的对象,它限定或包含关于异步操作的信息。
            //
            // 返回结果:
            //     用户定义的对象,它限定或包含关于异步操作的信息。
            object AsyncState { get; }
            //
            // 摘要:
            //     获取用于等待异步操作完成的 System.Threading.WaitHandle。
            //
            // 返回结果:
            //     用于等待异步操作完成的 System.Threading.WaitHandle。
            WaitHandle AsyncWaitHandle { get; }
            //
            // 摘要:
            //     获取一个值,该值指示异步操作是否同步完成。
            //
            // 返回结果:
            //     如果异步操作同步完成,则为 true;否则为 false。
            bool CompletedSynchronously { get; }
            //
            // 摘要:
            //     获取一个值,该值指示异步操作是否已完成。
            //
            // 返回结果:
            //     如果操作完成则为 true,否则为 false。
            bool IsCompleted { get; }
        }
    }

    TCPClientState 属性代码:

    public class TCPClientState
        {
            /// <summary>
            /// 与客户端相关的TcpClient
            /// </summary>
            public TcpClient TcpClient { get; private set; }
    
            /// <summary>
            /// 获取缓冲区
            /// </summary>
            public byte[] Buffer { get; private set; }
    
            /// <summary>
            /// 获取网络流
            /// </summary>
            public NetworkStream NetworkStream
            {
                get { return TcpClient.GetStream(); }
            }
    
            public TCPClientState(TcpClient tcpClient, byte[] buffer)
            {
                if (tcpClient == null)
                    throw new ArgumentNullException("tcpClient");
                if (buffer == null)
                    throw new ArgumentNullException("buffer");
    
                this.TcpClient = tcpClient;
                this.Buffer = buffer;
            }
            /// <summary>
            /// 关闭
            /// </summary>
            public void Close()
            {
                //关闭数据的接受和发送
                TcpClient.Close();
                Buffer = null;
            }
        }

    实例中的代码:

            /// <summary>
            /// 处理客户端连接的函数
            /// </summary>
            /// <param name="ar"></param>
            private void HandleTcpClientAccepted(IAsyncResult ar)
            {
                if (IsRunning)
                {
                    //TcpListener tcpListener = (TcpListener)ar.AsyncState;
    
                    TcpClient client = _listener.EndAcceptTcpClient(ar);
                    byte[] buffer = new byte[client.ReceiveBufferSize];
    
                    TCPClientState state
                      = new TCPClientState(client, buffer);
                    lock (_clients)
                    {
                        _clients.Add(state);
                        RaiseClientConnected(state);
                    }
    
                    NetworkStream stream = state.NetworkStream;
                    //开始异步读取数据
                    stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
    
                    _listener.BeginAcceptTcpClient(
                      new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);
                }
            }
            /// <summary>
            /// 数据接受回调函数
            /// </summary>
            /// <param name="ar"></param>
            private void HandleDataReceived(IAsyncResult ar)
            {
                if (IsRunning)
                {
                    TCPClientState state = (TCPClientState)ar.AsyncState;
                    NetworkStream stream = state.NetworkStream;
    
                    int recv = 0;
                    try
                    {
                        recv = stream.EndRead(ar);
                    }
                    catch
                    {
                        recv = 0;
                    }
    
                    if (recv == 0)
                    {
                        // connection has been closed
                        lock (_clients)
                        {
                            _clients.Remove(state);
                            //触发客户端连接断开事件
                            RaiseClientDisconnected(state);
                            return;
                        }
                    }
    
                    // received byte and trigger event notification
                    byte[] buff = new byte[recv];
                    Buffer.BlockCopy(state.Buffer, 0, buff, 0, recv);
                    //触发数据收到事件
                    RaiseDataReceived(state);
    
                    // continue listening for tcp datagram packets
                    stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
                }
            }
  • 相关阅读:
    SCAU 9504 面试
    SCAU 9503 懒人选座位
    SCAU 8628 相亲
    SCAU 10691 ACM 光环
    SCAU 8626 原子量计数
    SCAU 10674 等差对
    HDU ACM 1048 The Hardest Problem Ever (水题)
    SCAU 9502 ARDF
    SCAU 10686 DeathGod不知道的事情
    SCAU 8629 热身游戏(高精度)
  • 原文地址:https://www.cnblogs.com/im17me/p/10037092.html
Copyright © 2011-2022 走看看