• 经典代码IOCP的C#实现(转)


    using System;
    using System.Threading;  // Included for the Thread.Sleep call
    using Continuum.Threading;
    namespace Sample
    {
        //============================================
        /// <summary> Sample class for the threading class </summary>
        public class UtilThreadingSample
        {
            //*******************************************
            /// <summary> Test Method </summary>
            static void Main()
            {
                // Create the MSSQL IOCP Thread Pool
                IOCPThreadPool pThreadPool = new IOCPThreadPool(0, 5, 10, new IOCPThreadPool.USER_FUNCTION(IOCPThreadFunction));
                pThreadPool.PostEvent(10);
                Thread.Sleep(100);
                pThreadPool.Dispose();
            }
            //*****************************************
            /// <summary> Function to be called by the IOCP thread pool.  Called when
            ///           a command is posted for processing by the SocketManager </summary>
            /// <param name="iValue"> The value provided by the thread posting the event </param>
            static public void IOCPThreadFunction(Int32 iValue)
            {
                try
                {
                    Console.WriteLine("Value: {0}", iValue);
                }
                catch (Exception pException)
                {
                    Console.WriteLine(pException.Message);
                }
            }
        }
    }

     

    using System;
    using System.Threading;
    using System.Runtime.InteropServices;

    namespace Continuum.Threading
    {

        // Structures
        //==========================================
        /// <summary> This is the WIN32 OVERLAPPED structure </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public unsafe struct OVERLAPPED
        {
            UInt32* ulpInternal;
            UInt32* ulpInternalHigh;
            Int32 lOffset;
            Int32 lOffsetHigh;
            UInt32 hEvent;
        }

        // Classes
        //============================================
        /// <summary> This class provides the ability to create a thread pool to manage work.  The
        ///           class abstracts the Win32 IOCompletionPort API so it requires the use of
        ///           unmanaged code.  Unfortunately the .NET framework does not provide this functionality </summary>
        public sealed class IOCPThreadPool
        {

            // Win32 Function Prototypes
            /// <summary> Win32Func: Create an IO Completion Port Thread Pool </summary>
            [DllImport("Kernel32", CharSet = CharSet.Auto)]
            private unsafe static extern UInt32 CreateIoCompletionPort(UInt32 hFile, UInt32 hExistingCompletionPort, UInt32* puiCompletionKey, UInt32 uiNumberOfConcurrentThreads);

            /// <summary> Win32Func: Closes an IO Completion Port Thread Pool </summary>
            [DllImport("Kernel32", CharSet = CharSet.Auto)]
            private unsafe static extern Boolean CloseHandle(UInt32 hObject);

            /// <summary> Win32Func: Posts a context based event into an IO Completion Port Thread Pool </summary>
            [DllImport("Kernel32", CharSet = CharSet.Auto)]
            private unsafe static extern Boolean PostQueuedCompletionStatus(UInt32 hCompletionPort, UInt32 uiSizeOfArgument, UInt32* puiUserArg, OVERLAPPED* pOverlapped);

            /// <summary> Win32Func: Waits on a context based event from an IO Completion Port Thread Pool.
            ///           All threads in the pool wait in this Win32 Function </summary>
            [DllImport("Kernel32", CharSet = CharSet.Auto)]
            private unsafe static extern Boolean GetQueuedCompletionStatus(UInt32 hCompletionPort, UInt32* pSizeOfArgument, UInt32* puiUserArg, OVERLAPPED** ppOverlapped, UInt32 uiMilliseconds);

            // Constants
            /// <summary> SimTypeConst: This represents the Win32 Invalid Handle Value Macro </summary>
            private const UInt32 INVALID_HANDLE_VALUE = 0xffffffff;

            /// <summary> SimTypeConst: This represents the Win32 INFINITE Macro </summary>
            private const UInt32 INIFINITE = 0xffffffff;

            /// <summary> SimTypeConst: This tells the IOCP Function to shutdown </summary>
            private const Int32 SHUTDOWN_IOCPTHREAD = 0x7fffffff;


            // Delegate Function Types
            /// <summary> DelType: This is the type of user function to be supplied for the thread pool </summary>
            public delegate void USER_FUNCTION(Int32 iValue);


            // Private Properties
            private UInt32 m_hHandle;
            /// <summary> SimType: Contains the IO Completion Port Thread Pool handle for this instance </summary>
            private UInt32 GetHandle { get { return m_hHandle; } set { m_hHandle = value; } }

            private Int32 m_uiMaxConcurrency;
            /// <summary> SimType: The maximum number of threads that may be running at the same time </summary>
            private Int32 GetMaxConcurrency { get { return m_uiMaxConcurrency; } set { m_uiMaxConcurrency = value; } }

            private Int32 m_iMinThreadsInPool;
            /// <summary> SimType: The minimal number of threads the thread pool maintains </summary>
            private Int32 GetMinThreadsInPool { get { return m_iMinThreadsInPool; } set { m_iMinThreadsInPool = value; } }

            private Int32 m_iMaxThreadsInPool;
            /// <summary> SimType: The maximum number of threads the thread pool maintains </summary>
            private Int32 GetMaxThreadsInPool { get { return m_iMaxThreadsInPool; } set { m_iMaxThreadsInPool = value; } }

            private Object m_pCriticalSection;
            /// <summary> RefType: A serialization object to protect the class state </summary>
            private Object GetCriticalSection { get { return m_pCriticalSection; } set { m_pCriticalSection = value; } }

            private USER_FUNCTION m_pfnUserFunction;
            /// <summary> DelType: A reference to a user specified function to be call by the thread pool </summary>
            private USER_FUNCTION GetUserFunction { get { return m_pfnUserFunction; } set { m_pfnUserFunction = value; } }

            private Boolean m_bDisposeFlag;
            /// <summary> SimType: Flag to indicate if the class is disposing </summary>
            private Boolean IsDisposed { get { return m_bDisposeFlag; } set { m_bDisposeFlag = value; } }

            // Public Properties
            private Int32 m_iCurThreadsInPool;
            /// <summary> SimType: The current number of threads in the thread pool </summary>
            public Int32 GetCurThreadsInPool { get { return m_iCurThreadsInPool; } set { m_iCurThreadsInPool = value; } }
            /// <summary> SimType: Increment current number of threads in the thread pool </summary>
            private Int32 IncCurThreadsInPool() { return Interlocked.Increment(ref m_iCurThreadsInPool); }
            /// <summary> SimType: Decrement current number of threads in the thread pool </summary>
            private Int32 DecCurThreadsInPool() { return Interlocked.Decrement(ref m_iCurThreadsInPool); }
            private Int32 m_iActThreadsInPool;
            /// <summary> SimType: The current number of active threads in the thread pool </summary>
            public Int32 GetActThreadsInPool { get { return m_iActThreadsInPool; } set { m_iActThreadsInPool = value; } }
            /// <summary> SimType: Increment current number of active threads in the thread pool </summary>
            private Int32 IncActThreadsInPool() { return Interlocked.Increment(ref m_iActThreadsInPool); }
            /// <summary> SimType: Decrement current number of active threads in the thread pool </summary>
            private Int32 DecActThreadsInPool() { return Interlocked.Decrement(ref m_iActThreadsInPool); }
            private Int32 m_iCurWorkInPool;
            /// <summary> SimType: The current number of Work posted in the thread pool </summary>
            public Int32 GetCurWorkInPool { get { return m_iCurWorkInPool; } set { m_iCurWorkInPool = value; } }
            /// <summary> SimType: Increment current number of Work posted in the thread pool </summary>
            private Int32 IncCurWorkInPool() { return Interlocked.Increment(ref m_iCurWorkInPool); }
            /// <summary> SimType: Decrement current number of Work posted in the thread pool </summary>
            private Int32 DecCurWorkInPool() { return Interlocked.Decrement(ref m_iCurWorkInPool); }

            // Constructor, Finalize, and Dispose
            //***********************************************
            /// <summary> Constructor </summary>
            /// <param name = "iMaxConcurrency"> SimType: Max number of running threads allowed </param>
            /// <param name = "iMinThreadsInPool"> SimType: Min number of threads in the pool </param>
            /// <param name = "iMaxThreadsInPool"> SimType: Max number of threads in the pool </param>
            /// <param name = "pfnUserFunction"> DelType: Reference to a function to call to perform work </param>
            /// <exception cref = "Exception"> Unhandled Exception </exception>
            public IOCPThreadPool(Int32 iMaxConcurrency, Int32 iMinThreadsInPool, Int32 iMaxThreadsInPool, USER_FUNCTION pfnUserFunction)
            {
                try
                {
                    // Set initial class state
                    GetMaxConcurrency = iMaxConcurrency;
                    GetMinThreadsInPool = iMinThreadsInPool;
                    GetMaxThreadsInPool = iMaxThreadsInPool;
                    GetUserFunction = pfnUserFunction;
                    // Init the thread counters
                    GetCurThreadsInPool = 0;
                    GetActThreadsInPool = 0;
                    GetCurWorkInPool = 0;
                    // Initialize the Monitor Object
                    GetCriticalSection = new Object();
                    // Set the disposing flag to false
                    IsDisposed = false;
                    unsafe
                    {
                        // Create an IO Completion Port for Thread Pool use
                        GetHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, null, (UInt32)GetMaxConcurrency);
                    }
                    // Test to make sure the IO Completion Port was created
                    if (GetHandle == 0)
                        throw new Exception("Unable To Create IO Completion Port");
                    // Allocate and start the Minimum number of threads specified
                    Int32 iStartingCount = GetCurThreadsInPool;
                    ThreadStart tsThread = new ThreadStart(IOCPFunction);
                    for (Int32 iThread = 0; iThread < GetMinThreadsInPool; ++iThread)
                    {
                        // Create a thread and start it
                        Thread thThread = new Thread(tsThread);
                        thThread.Name = "IOCP " + thThread.GetHashCode();
                        thThread.Start();
                        // Increment the thread pool count
                        IncCurThreadsInPool();
                    }
                }
                catch
                {
                    throw new Exception("Unhandled Exception");
                }
            }

            //***********************************************
            /// <summary> Finalize called by the GC </summary>
            ~IOCPThreadPool()
            {
                if (!IsDisposed)
                    Dispose();
            }

            //**********************************************
            /// <summary> Called when the object will be shutdown.  This
            ///           function will wait for all of the work to be completed
            ///           inside the queue before completing </summary>
            public void Dispose()
            {
                try
                {
                    // Flag that we are disposing this object
                    IsDisposed = true;
                    // Get the current number of threads in the pool
                    Int32 iCurThreadsInPool = GetCurThreadsInPool;
                    // Shutdown all thread in the pool
                    for (Int32 iThread = 0; iThread < iCurThreadsInPool; ++iThread)
                    {
                        unsafe
                        {
                            bool bret = PostQueuedCompletionStatus(GetHandle, 4, (UInt32*)SHUTDOWN_IOCPTHREAD, null);
                        }
                    }
                    // Wait here until all the threads are gone
                    while (GetCurThreadsInPool != 0) Thread.Sleep(100);
                    unsafe
                    {
                        // Close the IOCP Handle
                        CloseHandle(GetHandle);
                    }
                }
                catch
                {
                }
            }

            // Private Methods
            //*******************************************
            /// <summary> IOCP Worker Function that calls the specified user function </summary>
            private void IOCPFunction()
            {
                UInt32 uiNumberOfBytes;
                Int32 iValue;
                try
                {
                    while (true)
                    {
                        unsafe
                        {
                            OVERLAPPED* pOv;
                            // Wait for an event
                            GetQueuedCompletionStatus(GetHandle, &uiNumberOfBytes, (UInt32*)&iValue, &pOv, INIFINITE);
                        }
                        // Decrement the number of events in queue
                        DecCurWorkInPool();
                        // Was this thread told to shutdown
                        if (iValue == SHUTDOWN_IOCPTHREAD)
                            break;
                        // Increment the number of active threads
                        IncActThreadsInPool();
                        try
                        {
                            // Call the user function
                            GetUserFunction(iValue);
                        }
                        catch
                        {
                        }
                        // Get a lock
                        Monitor.Enter(GetCriticalSection);
                        try
                        {
                            // If we have less than max threads currently in the pool
                            if (GetCurThreadsInPool < GetMaxThreadsInPool)
                            {
                                // Should we add a new thread to the pool
                                if (GetActThreadsInPool == GetCurThreadsInPool)
                                {
                                    if (IsDisposed == false)
                                    {
                                        // Create a thread and start it
                                        ThreadStart tsThread = new ThreadStart(IOCPFunction);
                                        Thread thThread = new Thread(tsThread);
                                        thThread.Name = "IOCP " + thThread.GetHashCode();
                                        thThread.Start();
                                        // Increment the thread pool count
                                        IncCurThreadsInPool();
                                    }
                                }
                            }
                        }
                        catch
                        {
                        }
                        // Relase the lock
                        Monitor.Exit(GetCriticalSection);
                        // Increment the number of active threads
                        DecActThreadsInPool();
                    }
                }
                catch
                {
                }
                // Decrement the thread pool count
                DecCurThreadsInPool();
            }

            // Public Methods
            //******************************************
            /// <summary> IOCP Worker Function that calls the specified user function </summary>
            /// <param name="iValue"> SimType: A value to be passed with the event </param>
            /// <exception cref = "Exception"> Unhandled Exception </exception>
            public void PostEvent(Int32 iValue)
            {
                try
                {
                    // Only add work if we are not disposing
                    if (IsDisposed == false)
                    {
                        unsafe
                        {
                            // Post an event into the IOCP Thread Pool
                            PostQueuedCompletionStatus(GetHandle, 4, (UInt32*)iValue, null);
                        }
                        // Increment the number of item of work
                        IncCurWorkInPool();
                        // Get a lock
                        Monitor.Enter(GetCriticalSection);
                        try
                        {
                            // If we have less than max threads currently in the pool
                            if (GetCurThreadsInPool < GetMaxThreadsInPool)
                            {
                                // Should we add a new thread to the pool
                                if (GetActThreadsInPool == GetCurThreadsInPool)
                                {
                                    if (IsDisposed == false)
                                    {
                                        // Create a thread and start it
                                        ThreadStart tsThread = new ThreadStart(IOCPFunction);
                                        Thread thThread = new Thread(tsThread);
                                        thThread.Name = "IOCP " + thThread.GetHashCode();
                                        thThread.Start();
                                        // Increment the thread pool count
                                        IncCurThreadsInPool();
                                    }
                                }
                            }
                        }
                        catch
                        {
                        }
                        // Release the lock
                        Monitor.Exit(GetCriticalSection);
                    }
                }
                catch (Exception e)
                {
                    throw e;
                }
                catch
                {
                    throw new Exception("Unhandled Exception");
                }
            }
            //*****************************************
            /// <summary> IOCP Worker Function that calls the specified user function </summary>
            /// <exception cref = "Exception"> Unhandled Exception </exception>
            public void PostEvent()
            {
                try
                {
                    // Only add work if we are not disposing
                    if (IsDisposed == false)
                    {
                        unsafe
                        {
                            // Post an event into the IOCP Thread Pool
                            PostQueuedCompletionStatus(GetHandle, 0, null, null);
                        }
                        // Increment the number of item of work
                        IncCurWorkInPool();
                        // Get a lock
                        Monitor.Enter(GetCriticalSection);
                        try
                        {
                            // If we have less than max threads currently in the pool
                            if (GetCurThreadsInPool < GetMaxThreadsInPool)
                            {
                                // Should we add a new thread to the pool
                                if (GetActThreadsInPool == GetCurThreadsInPool)
                                {
                                    if (IsDisposed == false)
                                    {
                                        // Create a thread and start it
                                        ThreadStart tsThread = new ThreadStart(IOCPFunction);
                                        Thread thThread = new Thread(tsThread);
                                        thThread.Name = "IOCP " + thThread.GetHashCode();
                                        thThread.Start();
                                        // Increment the thread pool count
                                        IncCurThreadsInPool();
                                    }
                                }
                            }
                        }
                        catch
                        {
                        }
                        // Release the lock
                        Monitor.Exit(GetCriticalSection);
                    }
                }
                catch (Exception e)
                {
                    throw e;
                }
                catch
                {
                    throw new Exception("Unhandled Exception");
                }
            }
        }
    }

     

  • 相关阅读:
    vue.js生成纵向拓扑图
    vue.js生成横向拓扑图
    Vue.js中使用wangEditor富文本编辑器
    文件上传与下载,PDF与Excel的操作
    Element布局实现日历布局
    golang时间转换
    iView学习笔记(四):Form表单操作
    iView学习笔记(三):表格搜索,过滤及隐藏列操作
    iView学习笔记(二):Table行编辑操作
    iView学习笔记(一):Table基本操作(包含前后端示例代码)
  • 原文地址:https://www.cnblogs.com/bigmouthz/p/946811.html
Copyright © 2020-2023  润新知