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 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);
            }
        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM