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);
                }
            }
  • 相关阅读:
    用于Web开发的8 个最好的跨平台编辑器
    javascript之数组操作
    15 个最佳的 jQuery 表格插件
    使用Backbone构建精美应用的7条建议
    linux内核内存分配(一、基本概念)
    redhat的systemd版本list
    Linux内核crash/Oops异常定位分析方法
    systemd bug: bz1437114 core:execute: fix fork() fail handling in exec_spawn()
    Use gdb attach pid and debug it
    Build rpm example:zram
  • 原文地址:https://www.cnblogs.com/im17me/p/10037092.html
Copyright © 2011-2022 走看看