問題: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 Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.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); } }