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

原文地址:https://www.cnblogs.com/Microshaoft/p/3600863.html