zoukankan      html  css  js  c++  java
  • Udp SocketAsyncEventArgs SocketAsyncDataHandler

    
    namespace Test
    {
        using Microshaoft;
        using System;
        using System.Net;
        using System.Net.Sockets;
        using System.Text;
        using System.Threading;
        using System.Threading.Tasks;
        class Program
        {
            static BufferManager _bufferManager;
            static SocketAsyncEventArgsPool _socketAsyncEventArgsPool;
            static void Main(string[] args)
            {
                args = new string[]
                            {
                                "127.0.0.1:10080"
                                , "127.0.0.1:10081"
                            };
                _bufferManager = new BufferManager
                                        (
                                            64 * 1024 * 1024
                                            , 64 * 1024
                                        );
                _bufferManager.InitBuffer();
                _socketAsyncEventArgsPool = new SocketAsyncEventArgsPool(100);
                var performanceCountersCategoryName = "Microshaoft EasyPerformanceCounters Category";
                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                    .AttachPerformanceCountersCategoryInstance
                                    (
                                        performanceCountersCategoryName
                                        , "Hander1::Sended"
                                    );
                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                    .AttachPerformanceCountersCategoryInstance
                                    (
                                        performanceCountersCategoryName
                                        , "Hander2::Sended"
                                    );
                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                    .AttachPerformanceCountersCategoryInstance
                                    (
                                        performanceCountersCategoryName
                                        , "Hander1::Received"
                                    );
                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                    .AttachPerformanceCountersCategoryInstance
                                    (
                                        performanceCountersCategoryName
                                        , "Hander2::Received"
                                    );
                Console.WriteLine(@"Press any key to Send! Press ""q"" to release resource");
                string s = string.Empty;
                while ((s = Console.ReadLine().ToLower()) != "q")
                {
                    Run(args);
                }
            }
            static void Run(string[] args)
            {
                var performanceCountersCategoryName = "Microshaoft EasyPerformanceCounters Category";
                var enableCounters = MultiPerformanceCountersTypeFlags.ProcessCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessedCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessingCounter;
                var sendEncoding = Encoding.Default;
                var receiveEncoding = Encoding.Default;
                //byte[] data = new byte[1024];
                string[] a = args[0].Split(new char[] { ':' });
                string ip = a[0];
                int port = int.Parse(a[1]);
                IPEndPoint ipep1 = new IPEndPoint(IPAddress.Parse(ip), port);
                Console.WriteLine("ipep1 {0}", ipep1.ToString());
                a = args[1].Split(new char[] { ':' });
                ip = a[0];
                port = int.Parse(a[1]);
                IPEndPoint ipep2 = new IPEndPoint(IPAddress.Parse(ip), port);
                Console.WriteLine("ipep2 {0}", ipep2.ToString());
                var remoteAnyIPEP = new IPEndPoint(IPAddress.Any, 0);
                Socket socket1 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                socket1.Bind(ipep1);
                SocketAsyncDataHandler<string> handler1 = new SocketAsyncDataHandler<string>(socket1, 1);
                var receiveSocketAsyncEventArgs1 = _socketAsyncEventArgsPool.Pop();
                _bufferManager.SetBuffer(receiveSocketAsyncEventArgs1);
                handler1.StartReceiveDataFrom
                            (
                                remoteAnyIPEP
                                , receiveSocketAsyncEventArgs1
                                , (x, y, z) =>
                                {
                                    Console.WriteLine("次数: {0}", x.ReceivedCount);
                                    Console.WriteLine("字节: {0}", y.Length);
                                    EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                        .CountPerformance
                                            (
                                                enableCounters
                                                , performanceCountersCategoryName
                                                , "Hander1::Received"
                                                , null
                                                , () =>
                                                {
                                                    var ss = receiveEncoding.GetString(y);
                                                    //Console.Write(s);
                                                    Console.WriteLine
                                                                (
                                                                    "from {0} , to {1}, data {2}"
                                                                    , x.WorkingSocket.LocalEndPoint
                                                                    , z.RemoteEndPoint
                                                                    , ss
                                                                );
                                                }
                                                , null
                                                , null
                                                , null
                                            );
                                    return false;
                                }
                                , (x, y, z) =>
                                {
                                    Console.WriteLine(z.ToString());
                                    return true;
                                }
                            );
                Socket socket2 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                socket2.Bind(ipep2);
                SocketAsyncDataHandler<string> handler2 = new SocketAsyncDataHandler<string>(socket2, 2);
                var receiveSocketAsyncEventArgs2 = _socketAsyncEventArgsPool.Pop();
                _bufferManager.SetBuffer(receiveSocketAsyncEventArgs2);
                handler2.StartReceiveDataFrom
                                (
                                    remoteAnyIPEP
                                    , receiveSocketAsyncEventArgs2
                                    , (x, y, z) =>
                                    {
                                        Console.WriteLine("次数: {0}", x.ReceivedCount);
                                        Console.WriteLine("字节: {0}", y.Length);
                                        EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                            .CountPerformance
                                                (
                                                    enableCounters
                                                    , performanceCountersCategoryName
                                                    , "Hander2::Received"
                                                    , null
                                                    , () =>
                                                    {
                                                        var ss = receiveEncoding.GetString(y);
                                                        //Console.Write(s);
                                                        Console.WriteLine
                                                                    (
                                                                        "from {0} , to {1}, data {2}"
                                                                        , x.WorkingSocket.LocalEndPoint
                                                                        , z.RemoteEndPoint
                                                                        , ss
                                                                    );
                                                    }
                                                    , null
                                                    , null
                                                    , null
                                                );
                                        return false;
                                    }
                                    , (x, y, z) =>
                                    {
                                        Console.WriteLine(z.ToString());
                                        return true;
                                    }
                                );
                string s = string.Empty;
                Console.WriteLine("Send ...");
                while ((s = Console.ReadLine().ToLower()) != "q")
                {
                    var buffer = sendEncoding.GetBytes(s);
                    Parallel.For
                            (
                                0
                                , 1000
                                , new ParallelOptions()
                                {
                                    MaxDegreeOfParallelism = 1// Environment.ProcessorCount
                                    //, TaskScheduler = null
                                }
                                , i =>
                                {
                                    Thread.Sleep(5);
                                    EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                        .CountPerformance
                                            (
                                                enableCounters
                                                , performanceCountersCategoryName
                                                , "Hander1::Sended"
                                                , null
                                                , () =>
                                                {
                                                    handler1.SendDataToSync(buffer, ipep2);
                                                }
                                                , null
                                                , null
                                                , null
                                            );
                                    EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                        .CountPerformance
                                            (
                                                enableCounters
                                                , performanceCountersCategoryName
                                                , "Hander2::Sended"
                                                , null
                                                , () =>
                                                {
                                                    handler2.SendDataToSync(buffer, ipep1);
                                                }
                                                , null
                                                , null
                                                , null
                                            );
                                }
                            );
                }
                var e = handler1.ReceiveSocketAsyncEventArgs;
                //_bufferManager.FreeBuffer(e);
                _socketAsyncEventArgsPool.Push(e);
                e = handler2.ReceiveSocketAsyncEventArgs;
                //_bufferManager.FreeBuffer(e);
                _socketAsyncEventArgsPool.Push(e);
                handler1.DestoryWorkingSocket();
                handler2.DestoryWorkingSocket();
                Console.WriteLine("Send quit");
            }
            //private static int _recieveCount = 0;
        }
    }
    namespace Microshaoft
    {
        using System.Collections.Concurrent;
        using System.Net.Sockets;
        // Represents a collection of reusable SocketAsyncEventArgs objects.
        public class SocketAsyncEventArgsPool
        {
            private ConcurrentStack<SocketAsyncEventArgs> _pool;
            public SocketAsyncEventArgsPool(int count)
            {
                _pool = new ConcurrentStack<SocketAsyncEventArgs>();
                for (var i = 0; i < count; i++)
                {
                    _pool.Push(new SocketAsyncEventArgs());
                }
            }
            // Add a SocketAsyncEventArg instance to the pool
            //
            //The "item" parameter is the SocketAsyncEventArgs instance
            // to add to the pool
            public void Push(SocketAsyncEventArgs socketAsyncEventArgs)
            {
                _pool.Push(socketAsyncEventArgs);
            }
            // Removes a SocketAsyncEventArgs instance from the pool
            // and returns the object removed from the pool
            public SocketAsyncEventArgs Pop()
            {
                SocketAsyncEventArgs socketAsyncEventArgs = null;
                if
                    (
                        _pool.IsEmpty
                        || !_pool.TryPop(out socketAsyncEventArgs)
                    )
                {
                    socketAsyncEventArgs = new SocketAsyncEventArgs();
                }
                return socketAsyncEventArgs;
            }
            // The number of SocketAsyncEventArgs instances in the pool
            public int Count
            {
                get
                {
                    return _pool.Count;
                }
            }
        }
    }
    namespace Microshaoft
    {
        using System.Collections.Concurrent;
        using System.Net.Sockets;
        public class BufferManager
        {
            // This class creates a single large buffer which can be divided up
            // and assigned to SocketAsyncEventArgs objects for use with each
            // socket I/O operation.
            // This enables buffers to be easily reused and guards against
            // fragmenting heap memory.
            //
            //This buffer is a byte array which the Windows TCP buffer can copy its data to.
            // the total number of bytes controlled by the buffer pool
            int _totalBytesInBufferBlock;
            // Byte array maintained by the Buffer Manager.
            byte[] _bufferBlock;
            ConcurrentStack<int> _freeIndexPool;
            int _currentIndex;
            int _bufferBytesAllocatedForEachSaea;
            public BufferManager(int totalBytes, int totalBufferBytesInEachSaeaObject)
            {
                _totalBytesInBufferBlock = totalBytes;
                _currentIndex = 0;
                _bufferBytesAllocatedForEachSaea = totalBufferBytesInEachSaeaObject;
                _freeIndexPool = new ConcurrentStack<int>();
            }
            // Allocates buffer space used by the buffer pool
            public void InitBuffer()
            {
                // Create one large buffer block.
                _bufferBlock = new byte[_totalBytesInBufferBlock];
            }
            // Divide that one large buffer block out to each SocketAsyncEventArg object.
            // Assign a buffer space from the buffer block to the
            // specified SocketAsyncEventArgs object.
            //
            // returns true if the buffer was successfully set, else false
            public bool SetBuffer(SocketAsyncEventArgs args)
            {
                int index = -1;
                if (_freeIndexPool.TryPop(out index))
                {
                    //This if-statement is only true if you have called the FreeBuffer
                    //method previously, which would put an offset for a buffer space
                    //back into this stack.
                    args.SetBuffer(_bufferBlock, index, _bufferBytesAllocatedForEachSaea);
                }
                else
                {
                    //Inside this else-statement is the code that is used to set the
                    //buffer for each SAEA object when the pool of SAEA objects is built
                    //in the Init method.
                    if ((_totalBytesInBufferBlock - _bufferBytesAllocatedForEachSaea) < _currentIndex)
                    {
                        return false;
                    }
                    args.SetBuffer(_bufferBlock, _currentIndex, _bufferBytesAllocatedForEachSaea);
                    _currentIndex += _bufferBytesAllocatedForEachSaea;
                }
                return true;
            }
            // Removes the buffer from a SocketAsyncEventArg object.   This frees the
            // buffer back to the buffer pool. Try NOT to use the FreeBuffer method,
            // unless you need to destroy the SAEA object, or maybe in the case
            // of some exception handling. Instead, on the server
            // keep the same buffer space assigned to one SAEA object for the duration of
            // this app's running.
            private void FreeBuffer(SocketAsyncEventArgs args)
            {
                _freeIndexPool.Push(args.Offset);
                args.SetBuffer(null, 0, 0);
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Net;
        using System.Net.Sockets;
        using System.Threading;
        public class SocketAsyncDataHandler<T>
        {
            private Socket _socket;
            public Socket WorkingSocket
            {
                get
                {
                    return _socket;
                }
            }
            //public int ReceiveDataBufferLength
            //{
            //    get;
            //    private set;
            //}
            public T ConnectionToken
            {
                get;
                set;
            }
            public IPAddress RemoteIPAddress
            {
                get
                {
                    return ((IPEndPoint) _socket.RemoteEndPoint).Address;
                }
            }
            public IPAddress LocalIPAddress
            {
                get
                {
                    return ((IPEndPoint) _socket.LocalEndPoint).Address;
                }
            }
            public int SocketID
            {
                get;
                private set;
            }
            public SocketAsyncDataHandler
                                (
                                    Socket socket
                                    , int socketID
                                )
            {
                _socket = socket;
                _isUdp = (_socket.ProtocolType == ProtocolType.Udp);
                _sendSocketAsyncEventArgs = new SocketAsyncEventArgs();
                SocketID = socketID;
            }
            private SocketAsyncEventArgs _sendSocketAsyncEventArgs;
            public int HeaderBytesLength
            {
                get;
                private set;
            }
            public int HeaderBytesOffset
            {
                get;
                private set;
            }
            private long _receivedCount = 0;
            public long ReceivedCount
            {
                get
                {
                    return _receivedCount;
                }
            }
            public int HeaderBytesCount
            {
                get;
                private set;
            }
            public SocketAsyncEventArgs ReceiveSocketAsyncEventArgs
            {
                get;
                private set;
            }
            private bool _isStartedReceiveData = false;
            private bool _isHeader = true;
            public bool StartReceiveWholeDataPackets
                                (
                                    int headerBytesLength
                                    , int headerBytesOffset
                                    , int headerBytesCount
                                    , Func<SocketAsyncEventArgs> getReceiveSocketAsyncEventArgsProcessFunc
                                    , Func
                                        <
                                            SocketAsyncDataHandler<T>
                                            , byte[]
                                            , SocketAsyncEventArgs
                                            , bool
                                        > onOneWholeDataPacketReceivedProcessFunc
                                    , Func
                                        <
                                            SocketAsyncDataHandler<T>
                                            , byte[]
                                            , SocketAsyncEventArgs
                                            , bool
                                        > onReceivedDataPacketErrorProcessFunc = null
                                    , Func
                                        <
                                            SocketAsyncDataHandler<T>
                                            , SocketAsyncEventArgs
                                            , Exception
                                            , bool
                                        > onCaughtExceptionProcessFunc = null
                                )
            {
                return
                    StartReceiveWholeDataPackets
                        (
                            headerBytesLength
                            , headerBytesOffset
                            , headerBytesCount
                            , getReceiveSocketAsyncEventArgsProcessFunc()
                            , onOneWholeDataPacketReceivedProcessFunc
                            , onReceivedDataPacketErrorProcessFunc
                            , onCaughtExceptionProcessFunc
                        );
            }
            public bool StartReceiveWholeDataPackets
                                (
                                    int headerBytesLength
                                    , int headerBytesOffset
                                    , int headerBytesCount
                                    , SocketAsyncEventArgs receiveSocketAsyncEventArgs
                                    , Func
                                        <
                                            SocketAsyncDataHandler<T>
                                            , byte[]
                                            , SocketAsyncEventArgs
                                            , bool
                                        > onOneWholeDataPacketReceivedProcessFunc
                                    , Func
                                        <
                                            SocketAsyncDataHandler<T>
                                            , byte[]
                                            , SocketAsyncEventArgs
                                            , bool
                                        > onReceivedDataPacketErrorProcessFunc = null
                                    , Func
                                        <
                                            SocketAsyncDataHandler<T>
                                            , SocketAsyncEventArgs
                                            , Exception
                                            , bool
                                        > onCaughtExceptionProcessFunc = null
                                )
            {
                if (!_isStartedReceiveData)
                {
                    HeaderBytesLength = headerBytesLength;
                    HeaderBytesOffset = headerBytesOffset;
                    HeaderBytesCount = headerBytesCount;
                    int bodyLength = 0;
                    ReceiveSocketAsyncEventArgs = receiveSocketAsyncEventArgs;
                    ReceiveSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>
                                    (
                                        (sender, e) =>
                                        {
                                            var socket = sender as Socket;
                                            if (e.BytesTransferred >= 0)
                                            {
                                                byte[] buffer = e.Buffer;
                                                int r = e.BytesTransferred;
                                                int p = e.Offset;
                                                int l = e.Count;
                                                if (r < l)
                                                {
                                                    p += r;
                                                    e.SetBuffer(p, l - r);
                                                }
                                                else if (r == l)
                                                {
                                                    if (_isHeader)
                                                    {
                                                        byte[] data = new byte[headerBytesCount];
                                                        Buffer.BlockCopy
                                                                    (
                                                                        buffer
                                                                        , HeaderBytesOffset
                                                                        , data
                                                                        , 0
                                                                        , data.Length
                                                                    );
                                                        byte[] intBytes = new byte[4];
                                                        l = (intBytes.Length < HeaderBytesCount ? intBytes.Length : HeaderBytesCount);
                                                        Buffer.BlockCopy
                                                                    (
                                                                        data
                                                                        , 0
                                                                        , intBytes
                                                                        , 0
                                                                        , l
                                                                    );
                                                        //Array.Reverse(intBytes);
                                                        bodyLength = BitConverter.ToInt32(intBytes, 0);
                                                        p += r;
                                                        e.SetBuffer(p, bodyLength);
                                                        Console.WriteLine(bodyLength);
                                                        _isHeader = false;
                                                    }
                                                    else
                                                    {
                                                        byte[] data = new byte[bodyLength + HeaderBytesLength];
                                                        bodyLength = 0;
                                                        Buffer.BlockCopy(buffer, 0, data, 0, data.Length);
                                                        _isHeader = true;
                                                        e.SetBuffer(0, HeaderBytesLength);
                                                        if (onOneWholeDataPacketReceivedProcessFunc != null)
                                                        {
                                                            onOneWholeDataPacketReceivedProcessFunc
                                                                (
                                                                    this
                                                                    , data
                                                                    , e
                                                                );
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    if (onReceivedDataPacketErrorProcessFunc != null)
                                                    {
                                                        byte[] data = new byte[p + r + HeaderBytesLength];
                                                        Buffer.BlockCopy(buffer, 0, data, 0, data.Length);
                                                        bool b = onReceivedDataPacketErrorProcessFunc
                                                                    (
                                                                        this
                                                                        , data
                                                                        , e
                                                                    );
                                                        if (b)
                                                        {
                                                            bool i = DestoryWorkingSocket();
                                                        }
                                                        else
                                                        {
                                                            _isHeader = true;
                                                            e.SetBuffer(0, HeaderBytesLength);
                                                        }
                                                    }
                                                }
                                            }
                                            if (!_isWorkingSocketDestoryed)
                                            {
                                                try
                                                {
                                                    socket.ReceiveAsync(e);
                                                }
                                                catch (Exception exception)
                                                {
                                                    var r = false;
                                                    if (onCaughtExceptionProcessFunc != null)
                                                    {
                                                        r = onCaughtExceptionProcessFunc
                                                                    (
                                                                        this
                                                                        , e
                                                                        , exception
                                                                    );
                                                    }
                                                    if (r)
                                                    {
                                                        DestoryWorkingSocket();
                                                    }
                                                }
                                            }
                                        }
                                    );
                    _socket.ReceiveAsync(ReceiveSocketAsyncEventArgs);
                    _isStartedReceiveData = true;
                }
                return _isStartedReceiveData;
            }
            private bool _isUdp = false;
            public bool IsUdp
            {
                get
                {
                    return _isUdp;
                }
            }
            private bool _isWorkingSocketDestoryed = false;
            public bool DestoryWorkingSocket()
            {
                //bool r = false;
                try
                {
                    if (_socket.Connected)
                    {
                        _socket.Disconnect(false);
                    }
                    _socket.Shutdown(SocketShutdown.Both);
                    _socket.Close();
                    _socket.Dispose();
                    _socket = null;
                    _isWorkingSocketDestoryed = true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    //r = false;
                }
                return _isWorkingSocketDestoryed;
            }
            public bool StartReceiveDataFrom
                (
                    EndPoint remoteEndPoint
                    , Func<SocketAsyncEventArgs> getReceiveSocketAsyncEventArgsProcessFunc
                    , Func
                        <
                            SocketAsyncDataHandler<T>
                            , byte[]
                            , SocketAsyncEventArgs
                            , bool
                        > onDataReceivedProcessFunc
                    , Func
                        <
                            SocketAsyncDataHandler<T>
                            , SocketAsyncEventArgs
                            , Exception
                            , bool
                        > onCaughtExceptionProcessFunc = null
                )
            {
                return
                    StartReceiveDataFrom
                        (
                            remoteEndPoint
                            , getReceiveSocketAsyncEventArgsProcessFunc()
                            , onDataReceivedProcessFunc
                            , onCaughtExceptionProcessFunc
                        );
            }
            public bool StartReceiveDataFrom
                        (
                            EndPoint remoteEndPoint
                            , SocketAsyncEventArgs receiveSocketAsyncEventArgs
                            , Func
                                <
                                    SocketAsyncDataHandler<T>
                                    , byte[]
                                    , SocketAsyncEventArgs
                                    , bool
                                > onDataReceivedProcessFunc
                            , Func
                                <
                                    SocketAsyncDataHandler<T>
                                    , SocketAsyncEventArgs
                                    , Exception
                                    , bool
                                > onCaughtExceptionProcessFunc = null
                        )
            {
                if (!_isStartedReceiveData)
                {
                    ReceiveSocketAsyncEventArgs = receiveSocketAsyncEventArgs;
                    ReceiveSocketAsyncEventArgs.RemoteEndPoint = remoteEndPoint;
                    ReceiveSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>
                                                    (
                                                        (sender, e) =>
                                                        {
                                                            Interlocked.Increment(ref _receivedCount);
                                                            var socket = sender as Socket;
                                                            int l = e.BytesTransferred;
                                                            //Console.WriteLine(l);
                                                            if (l > 0)
                                                            {
                                                                byte[] data = new byte[l];
                                                                var buffer = e.Buffer;
                                                                Buffer.BlockCopy(buffer, 0, data, 0, data.Length);
                                                                if (onDataReceivedProcessFunc != null)
                                                                {
                                                                    onDataReceivedProcessFunc(this, data, e);
                                                                    //Console.WriteLine(_receivedCount);
                                                                }
                                                            }
                                                            if (!_isWorkingSocketDestoryed)
                                                            {
                                                                try
                                                                {
                                                                    socket.ReceiveFromAsync(ReceiveSocketAsyncEventArgs);
                                                                }
                                                                catch (Exception exception)
                                                                {
                                                                    //Console.WriteLine(exception.ToString());
                                                                    var r = false;
                                                                    if (onCaughtExceptionProcessFunc != null)
                                                                    {
                                                                        r = onCaughtExceptionProcessFunc(this, ReceiveSocketAsyncEventArgs, exception);
                                                                    }
                                                                    if (r)
                                                                    {
                                                                        DestoryWorkingSocket();
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    );
                    _socket.ReceiveFromAsync(ReceiveSocketAsyncEventArgs);
                    _isStartedReceiveData = true;
                }
                return _isStartedReceiveData;
            }
            private object _sendSyncLockObject = new object();
            public int SendDataSync(byte[] data)
            {
                var r = -1;
                if (!_isUdp)
                {
                    lock (_sendSyncLockObject)
                    {
                        r = _socket.Send(data);
                    }
                }
                return r;
            }
            public int SendDataSyncWithRetry
                    (
                        byte[] data
                        , int retry = 3
                        , int sleepSeconds = 1
                    )
            {
                //增加就地重试机制
                int r = -1;
                int i = 0;
                while (i < retry)
                {
                    r = -1;
                    //lock (_sendSyncLockObject)
                    {
                        try
                        {
                            if (_socket != null)
                            {
                                r = SendDataSync(data);
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                    }
                    i++;
                    if (r > 0 || i == retry)
                    {
                        break;
                    }
                    else
                    {
                        Thread.Sleep(sleepSeconds * 1000);
                    }
                }
                return r;
            }
            public int SendDataToSync(byte[] data, EndPoint remoteEndPoint)
            {
                var r = -1;
                if (_isUdp)
                {
                    lock (_sendSyncLockObject)
                    {
                        r = _socket.SendTo(data, remoteEndPoint);
                    }
                }
                return r;
            }
            public int SendDataToSyncWithRetry
                            (
                                byte[] data
                                , EndPoint remoteEndPoint
                                , int retry = 3
                                , int sleepSeconds = 1
                            )
            {
                //增加就地重试机制
                int r = -1;
                int i = 0;
                while (i < retry)
                {
                    r = -1;
                    lock (_sendSyncLockObject)
                    {
                        try
                        {
                            if (_socket != null)
                            {
                                r = _socket.SendTo(data, remoteEndPoint);
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                    }
                    i++;
                    if (r > 0 || i == retry)
                    {
                        break;
                    }
                    else
                    {
                        Thread.Sleep(sleepSeconds * 1000);
                    }
                }
                return r;
            }
        }
    }
    namespace TestConsoleApplication
    {
        using System;
        using System.Diagnostics;
        using System.Threading;
        using System.Threading.Tasks;
        using Microshaoft;
        class Program
        {
            static void Main1(string[] args)
            {
                Console.WriteLine("Begin ...");
                Random r = new Random();
                int sleep = 2;
                int iterations = 10;
                int maxDegreeOfParallelism = 8; // Environment.ProcessorCount;
                var performanceCountersCategoryName = "Microshaoft EasyPerformanceCounters Category";
                var performanceCountersCategoryInstanceName
                        = string.Format
                                (
                                    "{2}{0}{3}{1}{4}"
                                    , ": "
                                    , " @ "
                                    , ""
                                    , ""
                                    , Process.GetCurrentProcess().ProcessName
                                );
                //EasyPerformanceCountersHelper 调用示例
                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                    .AttachPerformanceCountersCategoryInstance
                                    (
                                        performanceCountersCategoryName
                                        , performanceCountersCategoryInstanceName + "-1"
                                    );
                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                    .AttachPerformanceCountersCategoryInstance
                        (
                            performanceCountersCategoryName
                            , performanceCountersCategoryInstanceName + "-2"
                        );
                var enableCounters = MultiPerformanceCountersTypeFlags.ProcessCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessedCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter
                                        | MultiPerformanceCountersTypeFlags.ProcessingCounter;
                Parallel.For
                            (
                                0
                                , iterations
                                , new ParallelOptions()
                                {
                                    MaxDegreeOfParallelism = maxDegreeOfParallelism
                                }
                                , (x) =>
                                {
                                    EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                        .CountPerformance
                                            (
                                                enableCounters
                                                , performanceCountersCategoryName
                                                , performanceCountersCategoryInstanceName + "-1"
                                                , null
                                                , () =>
                                                {
                                                    sleep = r.Next(0, 5) * 1000;
                                                    //Thread.Sleep(sleep);
                                                    throw new Exception("sadsad");
                                                }
                                                , null
                                                , (xx) =>
                                                {
                                                    //Console.WriteLine("Exception {0}", xx.ToString());
                                                    return false;
                                                }
                                                , null
                                            );
                                }
                            );
                            Parallel.For
                                (
                                    0
                                    , iterations
                                    , new ParallelOptions()
                                    {
                                        MaxDegreeOfParallelism = maxDegreeOfParallelism
                                    }
                                    , (x) =>
                                    {
                                        Stopwatch stopwatch = null;
                                        try
                                        {
                                            stopwatch =
                                                EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                                    .CountPerformanceBegin
                                                        (
                                                            enableCounters
                                                            , performanceCountersCategoryName
                                                            , performanceCountersCategoryInstanceName + "-2"
                                                        );
                                            sleep = r.Next(0, 5) * 1000;
                                            //Thread.Sleep(sleep);
                                            throw new Exception("Test");
                                        }
                                        catch
                                        {
                                        }
                                        finally
                                        {
                                            EasyPerformanceCountersHelper<CommonPerformanceCountersContainer>
                                                .CountPerformanceEnd
                                                    (
                                                        enableCounters
                                                        , performanceCountersCategoryName
                                                        , performanceCountersCategoryInstanceName + "-2"
                                                        , stopwatch
                                                    );
                                        }
                                    }
                                );
                Console.WriteLine("End ...");
                Console.ReadLine();
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Collections.Generic;
        using System.Diagnostics;
        //using System.Collections.Concurrent;
        public static class EasyPerformanceCountersHelper<TPerformanceCountersContainer>
                                    where TPerformanceCountersContainer : class, IPerformanceCountersContainer, new ()
        {
            private static Dictionary<string, TPerformanceCountersContainer> _dictionary
                            = new Dictionary<string, TPerformanceCountersContainer>();
            public static void AttachPerformanceCountersCategoryInstance
                                (
                                    string performanceCountersCategoryName
                                    , string performanceCountersCategoryInstanceName
                                )
            {
                string key = string.Format
                                        (
                                            "{1}{0}{2}"
                                            , "-"
                                            , performanceCountersCategoryName
                                            , performanceCountersCategoryInstanceName
                                        );
                TPerformanceCountersContainer container = null;
                if (!_dictionary.TryGetValue(key, out container))
                {
                    container = new TPerformanceCountersContainer();
                    _dictionary.Add
                                (
                                    key
                                    , container
                                );
                    container
                        .AttachPerformanceCountersToProperties
                            (
                                performanceCountersCategoryInstanceName
                                , performanceCountersCategoryName
                            );
                }
            }
            private static object _lockerObject = new object();
            public static Stopwatch CountPerformanceBegin
                                        (
                                            MultiPerformanceCountersTypeFlags enabledPerformanceCounters
                                            , string performanceCountersCategoryName
                                            , string performanceCountersCategoryInstanceName
                                        )
            {
                Stopwatch r = null;
                if (enabledPerformanceCounters != MultiPerformanceCountersTypeFlags.None)
                {
                    string key = string.Format
                                            (
                                                "{1}{0}{2}"
                                                , "-"
                                                , performanceCountersCategoryName
                                                , performanceCountersCategoryInstanceName
                                            );
                    TPerformanceCountersContainer container = null;
                    if (!_dictionary.TryGetValue(key, out container))
                    {
                        lock (_lockerObject)
                        {
                            container = new TPerformanceCountersContainer();
                            _dictionary.Add
                                        (
                                            key
                                            , container
                                        );
                            container.AttachPerformanceCountersToProperties
                                                (
                                                    performanceCountersCategoryInstanceName
                                                    , performanceCountersCategoryName
                                                );
                        }
                    }
                    var enableProcessCounter =
                                                (
                                                    (
                                                        enabledPerformanceCounters
                                                        & MultiPerformanceCountersTypeFlags.ProcessCounter
                                                    )
                                                    != MultiPerformanceCountersTypeFlags.None
                                                );
                    if (enableProcessCounter)
                    {
                        container.PrcocessPerformanceCounter.Increment();
                    }
                    var enableProcessingCounter =
                                                (
                                                    (
                                                        enabledPerformanceCounters
                                                        & MultiPerformanceCountersTypeFlags.ProcessingCounter
                                                    )
                                                    != MultiPerformanceCountersTypeFlags.None
                                                );
                    if (enableProcessingCounter)
                    {
                        container.ProcessingPerformanceCounter.Increment();
                    }
                    var enableProcessedAverageTimerCounter =
                                                (
                                                    (
                                                        enabledPerformanceCounters
                                                        & MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter
                                                    )
                                                    != MultiPerformanceCountersTypeFlags.None
                                                );
                    if (enableProcessedAverageTimerCounter)
                    {
                        r = Stopwatch.StartNew();
                    }
                }
                return r;
            }
            public static void CountPerformanceEnd
                                        (
                                            MultiPerformanceCountersTypeFlags enabledPerformanceCounters
                                            , string performanceCountersCategoryName
                                            , string performanceCountersCategoryInstanceName
                                            , Stopwatch stopwatch
                                        )
            {
                string key = string.Format
                            (
                                "{1}{0}{2}"
                                , "-"
                                , performanceCountersCategoryName
                                , performanceCountersCategoryInstanceName
                            );
                TPerformanceCountersContainer container = null;
                if (!_dictionary.TryGetValue(key, out container))
                {
                    return;
                }
                var enableProcessedAverageTimerCounter =
                                            (
                                                (
                                                    enabledPerformanceCounters
                                                    & MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter
                                                )
                                                != MultiPerformanceCountersTypeFlags.None
                                            );
                if (enableProcessedAverageTimerCounter)
                {
                    if (stopwatch != null)
                    {
                        PerformanceCounter performanceCounter = container.ProcessedAverageTimerPerformanceCounter;
                        PerformanceCounter basePerformanceCounter = container.ProcessedAverageBasePerformanceCounter;
                        stopwatch.Stop();
                        performanceCounter.IncrementBy(stopwatch.ElapsedTicks);
                        basePerformanceCounter.Increment();
                        //stopwatch = null;
                    }
                }
                var enableProcessingCounter =
                                            (
                                                (
                                                    enabledPerformanceCounters
                                                    & MultiPerformanceCountersTypeFlags.ProcessingCounter
                                                )
                                                != MultiPerformanceCountersTypeFlags.None
                                            );
                if (enableProcessingCounter)
                {
                    container.ProcessingPerformanceCounter.Decrement();
                }
                var enableProcessedPerformanceCounter =
                                        (
                                            (
                                                enabledPerformanceCounters
                                                & MultiPerformanceCountersTypeFlags.ProcessedCounter
                                            )
                                            != MultiPerformanceCountersTypeFlags.None
                                        );
                if (enableProcessedPerformanceCounter)
                {
                    container.ProcessedPerformanceCounter.Increment();
                }
                var enableProcessedRateOfCountsPerSecondPerformanceCounter =
                            (
                                (
                                    enabledPerformanceCounters
                                    & MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter
                                )
                                != MultiPerformanceCountersTypeFlags.None
                            );
                if (enableProcessedRateOfCountsPerSecondPerformanceCounter)
                {
                    container.ProcessedRateOfCountsPerSecondPerformanceCounter.Increment();
                }
            }
            public static void CountPerformance
                                        (
                                            MultiPerformanceCountersTypeFlags enabledPerformanceCounters
                                            , string performanceCountersCategoryName
                                            , string performanceCountersCategoryInstanceName
                                            , Action onBeforeCountPerformanceInnerProcessAction
                                            , Action onCountPerformanceInnerProcessAction
                                            , Action onAfterCountPerformanceInnerProcessAction
                                            , Func<Exception, bool> onCaughtExceptionProcessFunc
                                            , Action<bool, Exception> onFinallyProcessAction
                                        )
            {
                if (enabledPerformanceCounters != MultiPerformanceCountersTypeFlags.None)
                {
                    if (onCountPerformanceInnerProcessAction != null)
                    {
                        string key = string.Format
                                                (
                                                    "{1}{0}{2}"
                                                    , "-"
                                                    , performanceCountersCategoryName
                                                    , performanceCountersCategoryInstanceName
                                                );
                        TPerformanceCountersContainer container = null;
                        if (!_dictionary.TryGetValue(key, out container))
                        {
                            lock (_lockerObject)
                            {
                                container = new TPerformanceCountersContainer();
                                _dictionary.Add
                                            (
                                                key
                                                , container
                                            );
                                container.AttachPerformanceCountersToProperties
                                                    (
                                                        performanceCountersCategoryInstanceName
                                                        , performanceCountersCategoryName
                                                    );
                            }
                        }
                        var enableProcessCounter =
                                                    (
                                                        (
                                                            enabledPerformanceCounters
                                                            & MultiPerformanceCountersTypeFlags.ProcessCounter
                                                        )
                                                        != MultiPerformanceCountersTypeFlags.None
                                                    );
                        if (enableProcessCounter)
                        {
                            container.PrcocessPerformanceCounter.Increment();
                        }
                        var enableProcessingCounter =
                                                    (
                                                        (
                                                            enabledPerformanceCounters
                                                            & MultiPerformanceCountersTypeFlags.ProcessingCounter
                                                        )
                                                        != MultiPerformanceCountersTypeFlags.None
                                                    );
                        if (enableProcessingCounter)
                        {
                            container.ProcessingPerformanceCounter.Increment();
                        }
                        var enableProcessedAverageTimerCounter =
                                                    (
                                                        (
                                                            enabledPerformanceCounters
                                                            & MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter
                                                        )
                                                        != MultiPerformanceCountersTypeFlags.None
                                                    );
                        var reThrowException = false;
                        container
                            .ProcessedAverageTimerPerformanceCounter
                                .ChangeAverageTimerCounterValueWithTryCatchExceptionFinally
                                            (
                                                enableProcessedAverageTimerCounter
                                                , container.ProcessedAverageBasePerformanceCounter
                                                , () =>
                                                {
                                                    if (onCountPerformanceInnerProcessAction != null)
                                                    {
                                                        if (onBeforeCountPerformanceInnerProcessAction != null)
                                                        {
                                                            onBeforeCountPerformanceInnerProcessAction();
                                                        }
                                                        onCountPerformanceInnerProcessAction();
                                                        if (onAfterCountPerformanceInnerProcessAction != null)
                                                        {
                                                            onAfterCountPerformanceInnerProcessAction();
                                                        }
                                                    }
                                                }
                                                , (x, y) =>        //catch
                                                {
                                                    container
                                                        .CaughtExceptionsPerformanceCounter
                                                            .Increment();
                                                    var r = reThrowException;
                                                    if (onCaughtExceptionProcessFunc != null)
                                                    {
                                                        r = onCaughtExceptionProcessFunc(y);
                                                    }
                                                    return r;
                                                }
                                                , (x, y, z, w) =>        //Finally
                                                {
                                                    if (enableProcessingCounter)
                                                    {
                                                        container.ProcessingPerformanceCounter.Decrement();
                                                    }
                                                    var enableProcessedPerformanceCounter =
                                                                            (
                                                                                (
                                                                                    enabledPerformanceCounters
                                                                                    & MultiPerformanceCountersTypeFlags.ProcessedCounter
                                                                                )
                                                                                != MultiPerformanceCountersTypeFlags.None
                                                                            );
                                                    if (enableProcessedPerformanceCounter)
                                                    {
                                                        container.ProcessedPerformanceCounter.Increment();
                                                    }
                                                    var enableProcessedRateOfCountsPerSecondPerformanceCounter =
                                                                            (
                                                                                (
                                                                                    enabledPerformanceCounters
                                                                                    & MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter
                                                                                )
                                                                                != MultiPerformanceCountersTypeFlags.None
                                                                            );
                                                    if (enableProcessedRateOfCountsPerSecondPerformanceCounter)
                                                    {
                                                        container
                                                            .ProcessedRateOfCountsPerSecondPerformanceCounter
                                                                .Increment();
                                                    }
                                                }
                                            );
                    }
                }
                else
                {
                    if (onCountPerformanceInnerProcessAction != null)
                    {
                        onCountPerformanceInnerProcessAction();
                    }
                }
            }
        }
    }
    namespace Microshaoft
    {
        using System.Diagnostics;
        public interface IPerformanceCountersContainer
        {
            PerformanceCounter CaughtExceptionsPerformanceCounter
            {
                get;
            }
            PerformanceCounter PrcocessPerformanceCounter
            {
                get;
            }
            PerformanceCounter ProcessingPerformanceCounter
            {
                get;
            }
            PerformanceCounter ProcessedPerformanceCounter
            {
                get;
            }
            PerformanceCounter ProcessedRateOfCountsPerSecondPerformanceCounter
            {
                get;
            }
            PerformanceCounter ProcessedAverageTimerPerformanceCounter
            {
                get;
            }
            PerformanceCounter ProcessedAverageBasePerformanceCounter
            {
                get;
            }
            void AttachPerformanceCountersToProperties
                                (
                                    string instanceName
                                    , string categoryName
                                );
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Diagnostics;
        public class CommonPerformanceCountersContainer
                        : IPerformanceCountersContainer
        {
            #region PerformanceCounters
            private PerformanceCounter _caughtExceptionsPerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.NumberOfItems64
                        , CounterName = "99.捕获异常次数(次)"
                    )
            ]
            public PerformanceCounter CaughtExceptionsPerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _caughtExceptionsPerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _caughtExceptionsPerformanceCounter;
                }
            }
            private PerformanceCounter _processPerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.NumberOfItems64
                        , CounterName = "01.接收处理笔数(笔)"
                    )
            ]
            public PerformanceCounter PrcocessPerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _processPerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _processPerformanceCounter;
                }
            }
            private PerformanceCounter _processingPerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.NumberOfItems64
                        , CounterName = "02.正在处理笔数(笔)"
                    )
            ]
            public PerformanceCounter ProcessingPerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _processingPerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _processingPerformanceCounter;
                }
            }
            private PerformanceCounter _processedPerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.NumberOfItems64
                        , CounterName = "03.完成处理笔数(笔)"
                    )
            ]
            public PerformanceCounter ProcessedPerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _processedPerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _processedPerformanceCounter;
                }
            }
            private PerformanceCounter _processedRateOfCountsPerSecondPerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.RateOfCountsPerSecond64
                        , CounterName = "04.每秒完成处理笔数(笔/秒)"
                    )
            ]
            public PerformanceCounter ProcessedRateOfCountsPerSecondPerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _processedRateOfCountsPerSecondPerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _processedRateOfCountsPerSecondPerformanceCounter;
                }
            }
            private PerformanceCounter _ProcessedAverageTimerPerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.AverageTimer32
                        , CounterName = "05.平均每笔处理耗时秒数(秒/笔)"
                    )
            ]
            public PerformanceCounter ProcessedAverageTimerPerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _ProcessedAverageTimerPerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _ProcessedAverageTimerPerformanceCounter;
                }
            }
            private PerformanceCounter _processedAverageBasePerformanceCounter;
            [
                PerformanceCounterDefinitionAttribute
                    (
                        CounterType = PerformanceCounterType.AverageBase
                    )
            ]
            public PerformanceCounter ProcessedAverageBasePerformanceCounter
            {
                private set
                {
                    ReaderWriterLockSlimHelper
                        .TryEnterWriterLockSlimWrite<PerformanceCounter>
                            (
                                ref _processedAverageBasePerformanceCounter
                                , value
                                , 2
                            );
                }
                get
                {
                    return _processedAverageBasePerformanceCounter;
                }
            }
            #endregion
            // indexer declaration
            public PerformanceCounter this[string name]
            {
                get
                {
                    throw new NotImplementedException();
                    //return null;
                }
            }
            //private bool _isAttachedPerformanceCounters = false;
            public void AttachPerformanceCountersToProperties
                                (
                                    string instanceName
                                    , string categoryName
                                )
            {
                var type = this.GetType();
                PerformanceCountersHelper
                    .AttachPerformanceCountersToProperties<CommonPerformanceCountersContainer>
                        (
                            instanceName
                            , categoryName
                            , this
                        );
            }
        }
    }
    //=========================================================================================
    //=========================================================================================
    namespace Microshaoft
    {
        using System;
        using System.Diagnostics;
        public static class PerformanceCounterExtensionMethodsManager
        {
            public static void ChangeAverageTimerCounterValueWithTryCatchExceptionFinally
                                    (
                                        this PerformanceCounter performanceCounter
                                        , bool enabled
                                        , PerformanceCounter basePerformanceCounter
                                        , Action onCountPerformanceInnerProcessAction //= null
                                        , Func<PerformanceCounter, Exception, bool> onCaughtExceptionProcessFunc //= null
                                        , Action<PerformanceCounter, PerformanceCounter, bool, Exception> onFinallyProcessAction //= null
                                    )
            {
                if (enabled)
                {
                    var stopwatch = Stopwatch.StartNew();
                    if (onCountPerformanceInnerProcessAction != null)
                    {
                        bool reThrowException = false;
                        TryCatchFinallyProcessHelper
                            .TryProcessCatchFinally
                                (
                                    true
                                    , () =>
                                    {
                                        onCountPerformanceInnerProcessAction();
                                    }
                                    , reThrowException
                                    , (x) =>
                                    {
                                        var r = reThrowException;
                                        if (onCaughtExceptionProcessFunc != null)
                                        {
                                            r = onCaughtExceptionProcessFunc(performanceCounter, x);
                                        }
                                        return r;
                                    }
                                    , (x, y) =>
                                    {
                                        stopwatch.Stop();
                                        performanceCounter.IncrementBy(stopwatch.ElapsedTicks);
                                        stopwatch = null;
                                        basePerformanceCounter.Increment();
                                        if (onFinallyProcessAction != null)
                                        {
                                            onFinallyProcessAction
                                                (
                                                    performanceCounter
                                                    , basePerformanceCounter
                                                    , x
                                                    , y
                                                );
                                        }
                                    }
                                );
                    }
                }
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Diagnostics;
        [FlagsAttribute]
        public enum MultiPerformanceCountersTypeFlags : ushort
        {
            None = 0,
            ProcessCounter = 1,
            ProcessingCounter = 2,
            ProcessedCounter = 4,
            ProcessedAverageTimerCounter = 8,
            ProcessedRateOfCountsPerSecondCounter = 16
        };
        [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
        public class PerformanceCounterDefinitionAttribute : Attribute
        {
            public PerformanceCounterType CounterType;
            public string CounterName;
        }
    }
    namespace Microshaoft
    {
        using System.Diagnostics;
        using System.Linq;
        public static class PerformanceCountersHelper
        {
            public static void AttachPerformanceCountersToProperties<T>
                                        (
                                            string performanceCounterInstanceName
                                            , string category
                                            , T target //= default(T)
                                        )
            {
                var type = typeof(T);
                var propertiesList = type.GetProperties().ToList();
                propertiesList = propertiesList.Where
                                                    (
                                                        (pi) =>
                                                        {
                                                            var parameters = pi.GetIndexParameters();
                                                            return
                                                                (
                                                                    pi.PropertyType == typeof(PerformanceCounter)
                                                                    && (parameters == null ? 0 : parameters.Length) <= 0
                                                                );
                                                        }
                                                    ).ToList();
                if (PerformanceCounterCategory.Exists(category))
                {
                    propertiesList.ForEach
                                        (
                                            (pi) =>
                                            {
                                                if (PerformanceCounterCategory.CounterExists(pi.Name, category))
                                                {
                                                    if (PerformanceCounterCategory.InstanceExists(performanceCounterInstanceName, category))
                                                    {
                                                        //var pc = new PerformanceCounter(category, pi.Name, instanceName, false);
                                                        //pc.InstanceName = instanceName;
                                                        //pc.RemoveInstance();
                                                    }
                                                }
                                            }
                                        );
                    //PerformanceCounterCategory.Delete(category);
                }
                if (!PerformanceCounterCategory.Exists(category))
                {
                    var ccdc = new CounterCreationDataCollection();
                    propertiesList.ForEach
                                    (
                                        (pi) =>
                                        {
                                            var propertyName = pi.Name;
                                            var performanceCounterType = PerformanceCounterType.NumberOfItems64;
                                            var performanceCounterName = propertyName;
                                            var attribute = pi.GetCustomAttributes(false).FirstOrDefault
                                                                                        (
                                                                                            (x) =>
                                                                                            {
                                                                                                return x as PerformanceCounterDefinitionAttribute != null;
                                                                                            }
                                                                                        ) as PerformanceCounterDefinitionAttribute;
                                            if (attribute != null)
                                            {
                                                var counterName = attribute.CounterName;
                                                if (!string.IsNullOrEmpty(counterName))
                                                {
                                                    performanceCounterName = counterName;
                                                }
                                                var counterType = attribute.CounterType;
                                                //if (counterType != null)
                                                {
                                                    performanceCounterType = counterType;
                                                }
                                            }
                                            var ccd = PerformanceCountersHelper
                                                        .GetCounterCreationData
                                                            (
                                                                performanceCounterName
                                                                , performanceCounterType
                                                            );
                                            ccdc.Add(ccd);
                                        }
                                    );
                    PerformanceCounterCategory.Create
                                    (
                                        category,
                                        string.Format("{0} Category Help.", category),
                                        PerformanceCounterCategoryType.MultiInstance,
                                        ccdc
                                    );
                }
                propertiesList.ForEach
                                (
                                    (pi) =>
                                    {
                                        var propertyName = pi.Name;
                                        var performanceCounterType = PerformanceCounterType.NumberOfItems64;
                                        var performanceCounterName = propertyName;
                                        var attribute =
                                                        pi
                                                            .GetCustomAttributes(false)
                                                                .FirstOrDefault
                                                                    (
                                                                        (x) =>
                                                                        {
                                                                            return
                                                                                (
                                                                                    (x as PerformanceCounterDefinitionAttribute)
                                                                                    != null
                                                                                );
                                                                        }
                                                                    ) as PerformanceCounterDefinitionAttribute;
                                        if (attribute != null)
                                        {
                                            var counterName = attribute.CounterName;
                                            if (!string.IsNullOrEmpty(counterName))
                                            {
                                                performanceCounterName = counterName;
                                            }
                                            var counterType = attribute.CounterType;
                                            //if (counterType != null)
                                            {
                                                performanceCounterType = counterType;
                                            }
                                        }
                                        var pc = new PerformanceCounter()
                                        {
                                            CategoryName = category
                                            ,
                                            CounterName = performanceCounterName
                                            ,
                                            InstanceLifetime = PerformanceCounterInstanceLifetime.Process
                                            ,
                                            InstanceName = performanceCounterInstanceName
                                            ,
                                            ReadOnly = false
                                            ,
                                            RawValue = 0
                                        };
                                        if (pi.GetGetMethod().IsStatic)
                                        {
                                            var setter =
                                                        DynamicPropertyAccessor
                                                            .CreateSetStaticPropertyValueAction<PerformanceCounter>
                                                                (
                                                                    type
                                                                    , propertyName
                                                                );
                                            setter(pc);
                                        }
                                        else
                                        {
                                            if (target != null)
                                            {
                                                var setter =
                                                            DynamicPropertyAccessor
                                                                .CreateSetPropertyValueAction<PerformanceCounter>
                                                                    (
                                                                        type
                                                                        , propertyName
                                                                    );
                                                setter(target, pc);
                                            }
                                        }
                                    }
                                );
            }
            public static CounterCreationData GetCounterCreationData
                                                (
                                                    string counterName
                                                    , PerformanceCounterType performanceCounterType
                                                )
            {
                return new CounterCreationData()
                {
                    CounterName = counterName
                    ,
                    CounterHelp = string.Format("{0} Help", counterName)
                    ,
                    CounterType = performanceCounterType
                };
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Threading;
        public static class ReaderWriterLockSlimHelper
        {
            public static bool TryEnterWriterLockSlimWrite<T>
                                                    (
                                                         ref T target
                                                        , T newValue
                                                        , int enterTimeOutSeconds
                                                    )
                                                        where T : class
            {
                bool r = false;
                var rwls = new ReaderWriterLockSlim();
                int timeOut = Timeout.Infinite;
                if (enterTimeOutSeconds >= 0)
                {
                    timeOut = enterTimeOutSeconds * 1000;
                }
                try
                {
                    r = (rwls.TryEnterWriteLock(timeOut));
                    if (r)
                    {
                        Interlocked.Exchange<T>(ref target, newValue);
                        r = true;
                    }
                }
                finally
                {
                    if (r)
                    {
                        rwls.ExitWriteLock();
                    }
                }
                return r;
            }
            public static bool TryEnterWriterLockSlim
                                    (
                                        Action action
                                        , int enterTimeOutSeconds
                                    )
            {
                bool r = false;
                if (action != null)
                {
                    var rwls = new ReaderWriterLockSlim();
                    int timeOut = Timeout.Infinite;
                    if (enterTimeOutSeconds >= 0)
                    {
                        timeOut = enterTimeOutSeconds * 1000;
                    }
                    try
                    {
                        r = (rwls.TryEnterWriteLock(timeOut));
                        if (r)
                        {
                            action();
                            r = true;
                        }
                    }
                    finally
                    {
                        if (r)
                        {
                            rwls.ExitWriteLock();
                        }
                    }
                }
                return r;
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Linq;
        using System.Linq.Expressions;
        using System.Reflection;
        public class DynamicPropertyAccessor
        {
            private static Assembly GetAssemblyByTypeName(string typeName)
            {
                return
                    AppDomain
                        .CurrentDomain
                            .GetAssemblies()
                                .First
                                    (
                                        (a) =>
                                        {
                                            return
                                                a
                                                    .GetTypes()
                                                        .Any
                                                            (
                                                                (t) =>
                                                                {
                                                                    return
                                                                        (
                                                                            t.FullName
                                                                            == typeName
                                                                        );
                                                                }
                                                            );
                                        }
                                    );
            }
            public static Func<object, object> CreateGetPropertyValueFunc
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateGetPropertyValueFunc(type, propertyName);
            }
            public static Func<object, object> CreateGetPropertyValueFunc
                            (
                                Type type
                                , string propertyName
                            )
            {
                var target = Expression.Parameter(typeof(object));
                var castTarget = Expression.Convert(target, type);
                var getPropertyValue = Expression.Property(castTarget, propertyName);
                var castPropertyValue = Expression.Convert(getPropertyValue, typeof(object));
                var lambda = Expression.Lambda<Func<object, object>>(castPropertyValue, target);
                return lambda.Compile();
            }
            public static Func<object, TProperty> CreateGetPropertyValueFunc<TProperty>
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateGetPropertyValueFunc<TProperty>(type, propertyName);
            }
            public static Func<object, TProperty> CreateGetPropertyValueFunc<TProperty>
                            (
                                Type type
                                , string propertyName
                            )
            {
                var target = Expression.Parameter(typeof(object));
                var castTarget = Expression.Convert(target, type);
                var getPropertyValue = Expression.Property(castTarget, propertyName);
                var lambda = Expression.Lambda<Func<object, TProperty>>(getPropertyValue, target);
                return lambda.Compile();
            }
            public static Func<TProperty> CreateGetStaticPropertyValueFunc<TProperty>
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateGetStaticPropertyValueFunc<TProperty>(type, propertyName);
            }
            public static Func<TProperty> CreateGetStaticPropertyValueFunc<TProperty>
                            (
                                Type type
                                , string propertyName
                            )
            {
                Func<TProperty> func = null;
                var property = type.GetProperty(propertyName, typeof(TProperty));
                if (property == null)
                {
                    property =
                                type
                                    .GetProperties()
                                        .ToList()
                                            .FirstOrDefault
                                                (
                                                    (x) =>
                                                    {
                                                        return
                                                            (
                                                                x.Name.ToLower()
                                                                == propertyName.ToLower()
                                                            );
                                                    }
                                                );
                }
                if (property != null)
                {
                    var getPropertyValue = Expression.Property(null, property);
                    var lambda = Expression.Lambda<Func<TProperty>>(getPropertyValue, null);
                    func = lambda.Compile();
                }
                return func;
            }
            public static Func<object> CreateGetStaticPropertyValueFunc
                            (
                                Type type
                                , string propertyName
                            )
            {
                Func<object> func = null;
                var property = type.GetProperty(propertyName);
                if (property == null)
                {
                    property =
                                type
                                    .GetProperties()
                                        .ToList()
                                            .FirstOrDefault
                                                (
                                                    (x) =>
                                                    {
                                                        return
                                                            (
                                                                x.Name.ToLower()
                                                                == propertyName.ToLower()
                                                            );
                                                    }
                                                );
                }
                if (property != null)
                {
                    var getPropertyValue = Expression.Property(null, property);
                    var castPropertyValue = Expression.Convert(getPropertyValue, typeof(object));
                    var lambda = Expression.Lambda<Func<object>>(castPropertyValue, null);
                    func = lambda.Compile();
                }
                return func;
            }
            public static Func<object> CreateGetStaticPropertyValueFunc
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateGetStaticPropertyValueFunc(type, propertyName);
            }
            public static Action<object, object> CreateSetPropertyValueAction
                            (
                                Type type
                                , string propertyName
                            )
            {
                Action<object, object> action = null;
                var property = type.GetProperty(propertyName);
                if (property == null)
                {
                    property =
                                type
                                    .GetProperties()
                                        .ToList()
                                            .FirstOrDefault
                                                (
                                                    (x) =>
                                                    {
                                                        return
                                                            (
                                                                x.Name.ToLower()
                                                                == propertyName.ToLower()
                                                            );
                                                    }
                                                );
                }
                if (property != null)
                {
                    var target = Expression.Parameter(typeof(object));
                    var propertyValue = Expression.Parameter(typeof(object));
                    var castTarget = Expression.Convert(target, type);
                    var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType);
                    var getSetMethod = property.GetSetMethod();
                    if (getSetMethod == null)
                    {
                        getSetMethod = property.GetSetMethod(true);
                    }
                    var call = Expression.Call(castTarget, getSetMethod, castPropertyValue);
                    var lambda = Expression.Lambda<Action<object, object>>(call, target, propertyValue);
                    action = lambda.Compile();
                }
                return action;
            }
            public static Action<object, object> CreateSetPropertyValueAction
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateSetPropertyValueAction(type, propertyName);
            }
            public static Action<object, TProperty> CreateSetPropertyValueAction<TProperty>
                            (
                                Type type
                                , string propertyName
                            )
            {
                Action<object, TProperty> action = null;
                var property = type.GetProperty(propertyName);
                if (property == null)
                {
                    property =
                                type
                                    .GetProperties()
                                        .ToList()
                                            .FirstOrDefault
                                                (
                                                    (x) =>
                                                    {
                                                        return
                                                            (
                                                                x.Name.ToLower()
                                                                == propertyName.ToLower()
                                                            );
                                                    }
                                                );
                }
                if (property != null)
                {
                    var target = Expression.Parameter(typeof(object));
                    var propertyValue = Expression.Parameter(typeof(TProperty));
                    var castTarget = Expression.Convert(target, type);
                    var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType);
                    var getSetMethod = property.GetSetMethod();
                    if (getSetMethod == null)
                    {
                        getSetMethod = property.GetSetMethod(true);
                    }
                    var call = Expression.Call(castTarget, getSetMethod, castPropertyValue);
                    var lambda = Expression.Lambda<Action<object, TProperty>>(call, target, propertyValue);
                    action = lambda.Compile();
                }
                return action;
            }
            public static Action<object, TProperty> CreateSetPropertyValueAction<TProperty>
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateSetPropertyValueAction<TProperty>(type, propertyName);
            }
            public static Action<object> CreateSetStaticPropertyValueAction
                            (
                                Type type
                                , string propertyName
                            )
            {
                Action<object> action = null;
                var property = type.GetProperty(propertyName);
                if (property == null)
                {
                    property =
                                type
                                    .GetProperties()
                                        .ToList()
                                            .FirstOrDefault
                                                (
                                                    (x) =>
                                                    {
                                                        return
                                                            (
                                                                x.Name.ToLower()
                                                                == propertyName.ToLower()
                                                            );
                                                    }
                                                );
                }
                if (property != null)
                {
                    var propertyValue = Expression.Parameter(typeof(object));
                    var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType);
                    var getSetMethod = property.GetSetMethod();
                    if (getSetMethod == null)
                    {
                        getSetMethod = property.GetSetMethod(true);
                    }
                    var call = Expression.Call(null, getSetMethod, castPropertyValue);
                    var lambda = Expression.Lambda<Action<object>>(call, propertyValue);
                    action = lambda.Compile();
                }
                return action;
            }
            public static Action<object> CreateSetStaticPropertyValueAction
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateSetStaticPropertyValueAction(type, propertyName);
            }
            public static Action<TProperty> CreateSetStaticPropertyValueAction<TProperty>
                            (
                                Type type
                                , string propertyName
                            )
            {
                Action<TProperty> action = null;
                var property = type.GetProperty(propertyName);
                if (property == null)
                {
                    property =
                                type
                                    .GetProperties()
                                        .ToList()
                                            .FirstOrDefault
                                                (
                                                    (x) =>
                                                    {
                                                        return
                                                            (
                                                                x.Name.ToLower()
                                                                == propertyName.ToLower()
                                                            );
                                                    }
                                                );
                }
                if (property != null)
                {
                    var propertyValue = Expression.Parameter(typeof(TProperty));
                    //var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType);
                    var getSetMethod = property.GetSetMethod();
                    if (getSetMethod == null)
                    {
                        getSetMethod = property.GetSetMethod(true);
                    }
                    var call = Expression.Call(null, getSetMethod, propertyValue);
                    var lambda = Expression.Lambda<Action<TProperty>>(call, propertyValue);
                    action = lambda.Compile();
                }
                return action;
            }
            public static Action<TProperty> CreateSetStaticPropertyValueAction<TProperty>
                            (
                                string typeName
                                , string propertyName
                                , bool isTypeFromAssembly = false
                            )
            {
                Type type;
                if (isTypeFromAssembly)
                {
                    var assembly = GetAssemblyByTypeName(typeName);
                    type = assembly.GetType(typeName);
                }
                else
                {
                    type = Type.GetType(typeName);
                }
                return CreateSetStaticPropertyValueAction<TProperty>(type, propertyName);
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Diagnostics;
        using System.Reflection;
        using System.Threading.Tasks;
        public static class TryCatchFinallyProcessHelper
        {
            public static async Task<T> TryProcessCatchFinallyAsync<T>
                                        (
                                            bool needTry
                                            , Func<Task<T>> onTryProcessFunc
                                            , bool reThrowException = false
                                            , Func<Exception, bool> onCaughtExceptionProcessFunc = null
                                            , Action<bool, Exception> onFinallyProcessAction = null
                                        )
            {
                T r = default(T);
                //if (onTryProcessAction != null)
                {
                    if (needTry)
                    {
                        Exception exception = null;
                        var caughtException = false;
                        try
                        {
                            r = await onTryProcessFunc();
                            return r;
                        }
                        catch (Exception e)
                        {
                            caughtException = true;
                            exception = e;
                            var currentCalleeMethod = MethodInfo.GetCurrentMethod();
                            var currentCalleeType = currentCalleeMethod.DeclaringType;
                            StackTrace stackTrace = new StackTrace();
                            StackFrame stackFrame = stackTrace.GetFrame(1);
                            var callerMethod = stackFrame.GetMethod();
                            var callerType = callerMethod.DeclaringType;
                            var frame = (stackTrace.FrameCount > 1 ? stackTrace.FrameCount - 1 : 1);
                            stackFrame = stackTrace.GetFrame(frame);
                            var originalCallerMethod = stackFrame.GetMethod();
                            var originalCallerType = originalCallerMethod.DeclaringType;
                            var innerExceptionMessage = string.Format
                                    (
                                        "Rethrow caught [{1}] Exception{0} at Callee Method: [{2}]{0} at Caller Method: [{3}]{0} at Original Caller Method: [{4}]"
                                        , "
    	"
                                        , e.Message
                                        , string.Format("{1}{0}{2}", "::", currentCalleeType, currentCalleeMethod)
                                        , string.Format("{1}{0}{2}", "::", callerType, callerMethod)
                                        , string.Format("{1}{0}{2}", "::", originalCallerType, originalCallerMethod)
                                    );
                            Console.WriteLine(innerExceptionMessage);
                            if (onCaughtExceptionProcessFunc != null)
                            {
                                reThrowException = onCaughtExceptionProcessFunc(e);
                            }
                            if (reThrowException)
                            {
                                throw
                                    new Exception
                                            (
                                                innerExceptionMessage
                                                , e
                                            );
                            }
                            return r;
                        }
                        finally
                        {
                            if (onFinallyProcessAction != null)
                            {
                                onFinallyProcessAction(caughtException, exception);
                            }
                        }
                    }
                    else
                    {
                        return await onTryProcessFunc();
                    }
                }
            }
            public static void TryProcessCatchFinally
                                        (
                                            bool needTry
                                            , Action onTryProcessAction
                                            , bool reThrowException = false
                                            , Func<Exception, bool> onCaughtExceptionProcessFunc = null
                                            , Action<bool, Exception> onFinallyProcessAction = null
                                        )
            {
                if (onTryProcessAction != null)
                {
                    if (needTry)
                    {
                        Exception exception = null;
                        var caughtException = false;
                        try
                        {
                            onTryProcessAction();
                        }
                        catch (Exception e)
                        {
                            caughtException = true;
                            exception = e;
                            var currentCalleeMethod = MethodInfo.GetCurrentMethod();
                            var currentCalleeType = currentCalleeMethod.DeclaringType;
                            StackTrace stackTrace = new StackTrace(e, true);
                            StackFrame stackFrame = stackTrace.GetFrame(1);
                            var callerMethod = stackFrame.GetMethod();
                            var callerType = callerMethod.DeclaringType;
                            var frame = (stackTrace.FrameCount > 1 ? stackTrace.FrameCount - 1 : 1);
                            stackFrame = stackTrace.GetFrame(frame);
                            var originalCallerMethod = stackFrame.GetMethod();
                            var originalCallerType = originalCallerMethod.DeclaringType;
                            var innerExceptionMessage = string.Format
                                    (
                                        "Rethrow caught [{1}] Exception{0} at Callee Method: [{2}]{0} at Caller Method: [{3}]{0} at Original Caller Method: [{4}]"
                                        , "
    	"
                                        , e.Message
                                        , string.Format("{1}{0}{2}", "::", currentCalleeType, currentCalleeMethod)
                                        , string.Format("{1}{0}{2}", "::", callerType, callerMethod)
                                        , string.Format("{1}{0}{2}", "::", originalCallerType, originalCallerMethod)
                                    );
                            //Console.WriteLine(innerExceptionMessage);
                            if (onCaughtExceptionProcessFunc != null)
                            {
                                reThrowException = onCaughtExceptionProcessFunc(e);
                            }
                            if (reThrowException)
                            {
                                throw
                                    new Exception
                                            (
                                                innerExceptionMessage
                                                , e
                                            );
                            }
                        }
                        finally
                        {
                            //Console.WriteLine("Finally");
                            if (onFinallyProcessAction != null)
                            {
                                onFinallyProcessAction(caughtException, exception);
                            }
                        }
                    }
                    else
                    {
                        onTryProcessAction();
                    }
                }
            }
        }
    }
    
    
  • 相关阅读:
    【Appium】appium踩坑记录:解决每次安装appium setting和Unlock
    Pycharm from XXX import XXX 引入本地文件标红报错(source_path&Python package)
    🍖02 不同平台更换pip源
    🍖pycharm 更换 pip 下载源
    🍖01 路飞学城项目分析
    🍖Vue-cli 创建项目
    🍖Vue 与后端交互
    🍖Vue 计算属性
    🍖Vue 虚拟DOM与Diff算法简介
    🍖Vue 生命期钩子
  • 原文地址:https://www.cnblogs.com/Microshaoft/p/3600863.html
Copyright © 2011-2022 走看看