问题: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); } }