[C#]I/O完成端口的类定义和测试实例

整理者:郑昀@UltraPower
日期:2005-04-13

从William Kennedy那里整理过来的,不同之处在于他自己定义了一个Overlapped,而我们这里直接使用
System.Threading.NativeOverlapped:。

附一段我以前的Win32下的IOCP文档,如果您了解IOCP也可以直接跳过看后面的C#测试示范:

我们采用的是I/O Complete Port(以下简称IOCP)处理机制。

简单的讲,当服务应用程序初始化时,它应该先创建一个I/O CP。我们在请求到来后,将得到的数据打包用PostQueuedCompletionStatus发送到IOCP中。这时需要创建一些个线程(7个线程/CPU,再多就没有意义了)来处理发送到IOCP端口的消息。实现步骤大致如下:

1     先在主线程中调用CreateIoCompletionPort创建IOCP

CreateIoCompletionPort的前三个参数只在把设备同Complete Port相关联时才有用。

此时我们只需传递INVALID_HANDLE_VALUE,NULL0即可。

第四个参数告诉端口同时能运行的最多线程数,这里设置为0,表示默认为当前计算机的CPU数目。

2     我们的ThreadFun线程函数执行一些初始化之后,将进入一个循环,该循环会在服务进程终止时才结束。

在循环中,调用GetQueuedCompletionStatus,这样就把当前线程的ID放入一个等待线程队列中,I/O CP内核对象就总能知道哪个线程在等待处理完成的I/O请求。

如果在IDLE_THREAD_TIMEOUT规定的时间内I/O CP上还没有出现一个Completion Packet,则转入下一次循环。在这里我们设置的IDLE_THREAD_TIMEOUT1秒。

 

当端口的I/O完成队列中出现一项时,完成端口就唤醒等待线程队列中的这个线程,该线程将得到完成的I/O项中的信息:       传输的字节数、完成键和OVERLAPPED结构的地址。

 

在我们的程序中可以用智能指针或者BSTR或者int来接受这个OVERLAPPED结构的地址的值,从而得到消息;然后在这个线程中处理消息。

GetQueuedCompletionStatus的第一个参数hCompletionPort指出了要监视哪一个端口,这里我们传送先前从CreateIoCompletionPort返回的端口句柄。

 

需要注意的是:

第一,   线程池的数目是有限制的,和CPU数目有关系。

第二,   IOCP是一种较为完美的睡眠/唤醒 线程机制;线程当前没有任务要处理时,就进入睡眠状态,从而不占用CPU资源,直到被内核唤醒;

第三,   最近一次刚执行完的线程,下次任务来的时候还会唤醒它;所以有可能比较少被调用的线程以后被调用的几率也少。

 


测试代码:
None.gif
None.gif
using  System;
None.gif
using  System.Threading;   //  Included for the Thread.Sleep call
None.gif
using  Continuum.Threading;
None.gif
using  System.Runtime.InteropServices;
None.gif
None.gif
namespace  IOCPDemo
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
//=============================================================================
ExpandedSubBlockStart.gifContractedSubBlock.gif
    /**//// <summary> Sample class for the threading class </summary>
InBlock.gif    public class UtilThreadingSample
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//*****************************************************************************   
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <summary> Test Method </summary>
InBlock.gif        static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// Create the MSSQL IOCP Thread Pool
InBlock.gif
            IOCPThreadPool pThreadPool = new IOCPThreadPool(01020new IOCPThreadPool.USER_FUNCTION(IOCPThreadFunction));
InBlock.gif      
InBlock.gif            
//for(int i =1;i<10000;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif{
InBlock.gif                pThreadPool.PostEvent(
1234);
ExpandedSubBlockEnd.gif            }

InBlock.gif      
InBlock.gif            Thread.Sleep(
100);
InBlock.gif      
InBlock.gif            pThreadPool.Dispose();
ExpandedSubBlockEnd.gif        }

InBlock.gif    
InBlock.gif        
//********************************************************************
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <summary> Function to be called by the IOCP thread pool.  Called when
InBlock.gif        
///           a command is posted for processing by the SocketManager </summary>
ExpandedSubBlockEnd.gif        
/// <param name="iValue"> The value provided by the thread posting the event </param>

InBlock.gif        static public void IOCPThreadFunction(int iValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(
"Value: {0}", iValue.ToString());
InBlock.gif                Thread.Sleep(
3000);
ExpandedSubBlockEnd.gif            }

InBlock.gif      
InBlock.gif            
catch (Exception pException)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(pException.Message);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif


类代码:
None.gif using  System;
None.gif
using  System.Threading;
None.gif
using  System.Runtime.InteropServices;
None.gif
None.gif
namespace  IOCPThreading
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [StructLayout(LayoutKind.Sequential, CharSet
=CharSet.Auto)]
InBlock.gif
InBlock.gif    
public sealed class IOCPThreadPool
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        [DllImport(
"Kernel32", CharSet=CharSet.Auto)]
InBlock.gif        
private unsafe static extern UInt32 CreateIoCompletionPort(UInt32 hFile, UInt32 hExistingCompletionPort, UInt32* puiCompletionKey, UInt32 uiNumberOfConcurrentThreads);
InBlock.gif
InBlock.gif        [DllImport(
"Kernel32", CharSet=CharSet.Auto)]
InBlock.gif        
private unsafe static extern Boolean CloseHandle(UInt32 hObject);
InBlock.gif
InBlock.gif        [DllImport(
"Kernel32", CharSet=CharSet.Auto)]
InBlock.gif        
private unsafe static extern Boolean PostQueuedCompletionStatus(UInt32 hCompletionPort, UInt32 uiSizeOfArgument, UInt32* puiUserArg, System.Threading.NativeOverlapped* pOverlapped);
InBlock.gif
InBlock.gif        [DllImport(
"Kernel32", CharSet=CharSet.Auto)]
InBlock.gif        
private unsafe static extern Boolean GetQueuedCompletionStatus(UInt32 hCompletionPort, UInt32* pSizeOfArgument, UInt32* puiUserArg, System.Threading.NativeOverlapped** ppOverlapped, UInt32 uiMilliseconds);
InBlock.gif
InBlock.gif        
private const UInt32 INVALID_HANDLE_VALUE = 0xffffffff;
InBlock.gif        
private const UInt32 INIFINITE = 0xffffffff;
InBlock.gif        
private const Int32 SHUTDOWN_IOCPTHREAD = 0x7fffffff;
InBlock.gif        
public delegate void USER_FUNCTION(int iValue);
InBlock.gif        
private UInt32 m_hHandle;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private UInt32 GetHandle dot.gifget dot.gifreturn m_hHandle; } set dot.gif{ m_hHandle = value; } }
InBlock.gif
InBlock.gif        
private Int32 m_uiMaxConcurrency;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 GetMaxConcurrency dot.gifget dot.gifreturn m_uiMaxConcurrency; } set dot.gif{ m_uiMaxConcurrency = value; } }
InBlock.gif
InBlock.gif
InBlock.gif        
private Int32 m_iMinThreadsInPool;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 GetMinThreadsInPool dot.gifget dot.gifreturn m_iMinThreadsInPool; } set dot.gif{ m_iMinThreadsInPool = value; } }
InBlock.gif
InBlock.gif        
private Int32 m_iMaxThreadsInPool;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 GetMaxThreadsInPool dot.gifget dot.gifreturn m_iMaxThreadsInPool; } set dot.gif{ m_iMaxThreadsInPool = value; } }
InBlock.gif
InBlock.gif
InBlock.gif        
private Object m_pCriticalSection;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Object GetCriticalSection dot.gifget dot.gifreturn m_pCriticalSection; } set dot.gif{ m_pCriticalSection = value; } }
InBlock.gif
InBlock.gif
InBlock.gif        
private USER_FUNCTION m_pfnUserFunction;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private USER_FUNCTION GetUserFunction dot.gifget dot.gifreturn m_pfnUserFunction; } set dot.gif{ m_pfnUserFunction = value; } }
InBlock.gif
InBlock.gif
InBlock.gif        
private Boolean m_bDisposeFlag;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Flag to indicate if the class is disposing </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Boolean IsDisposed dot.gifget dot.gifreturn m_bDisposeFlag; } set dot.gif{ m_bDisposeFlag = value; } }
InBlock.gif
InBlock.gif        
private Int32 m_iCurThreadsInPool;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: The current number of threads in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public Int32 GetCurThreadsInPool dot.gifget dot.gifreturn m_iCurThreadsInPool; } set dot.gif{ m_iCurThreadsInPool = value; } }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Increment current number of threads in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 IncCurThreadsInPool() dot.gifreturn Interlocked.Increment(ref m_iCurThreadsInPool); }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Decrement current number of threads in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 DecCurThreadsInPool() dot.gifreturn Interlocked.Decrement(ref m_iCurThreadsInPool); }
InBlock.gif
InBlock.gif
InBlock.gif        
private Int32 m_iActThreadsInPool;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: The current number of active threads in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public Int32 GetActThreadsInPool dot.gifget dot.gifreturn m_iActThreadsInPool; } set dot.gif{ m_iActThreadsInPool = value; } }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Increment current number of active threads in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 IncActThreadsInPool() dot.gifreturn Interlocked.Increment(ref m_iActThreadsInPool); }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Decrement current number of active threads in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 DecActThreadsInPool() dot.gifreturn Interlocked.Decrement(ref m_iActThreadsInPool); }
InBlock.gif
InBlock.gif
InBlock.gif        
private Int32 m_iCurWorkInPool;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: The current number of Work posted in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public Int32 GetCurWorkInPool dot.gifget dot.gifreturn m_iCurWorkInPool; } set dot.gif{ m_iCurWorkInPool = value; } }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Increment current number of Work posted in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 IncCurWorkInPool() dot.gifreturn Interlocked.Increment(ref m_iCurWorkInPool); }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> SimType: Decrement current number of Work posted in the thread pool </summary>
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private Int32 DecCurWorkInPool() dot.gifreturn Interlocked.Decrement(ref m_iCurWorkInPool); }
InBlock.gif
InBlock.gif        
public IOCPThreadPool(Int32 iMaxConcurrency, Int32 iMinThreadsInPool, Int32 iMaxThreadsInPool, USER_FUNCTION pfnUserFunction)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// Set initial class state
InBlock.gif

InBlock.gif                GetMaxConcurrency   
= iMaxConcurrency;
InBlock.gif
InBlock.gif                GetMinThreadsInPool 
= iMinThreadsInPool;
InBlock.gif
InBlock.gif                GetMaxThreadsInPool 
= iMaxThreadsInPool;
InBlock.gif
InBlock.gif                GetUserFunction     
= pfnUserFunction;
InBlock.gif
InBlock.gif
InBlock.gif                
// Init the thread counters
InBlock.gif

InBlock.gif                GetCurThreadsInPool 
= 0;
InBlock.gif
InBlock.gif                GetActThreadsInPool 
= 0;
InBlock.gif
InBlock.gif                GetCurWorkInPool    
= 0;
InBlock.gif
InBlock.gif
InBlock.gif                
// Initialize the Monitor Object
InBlock.gif

InBlock.gif                GetCriticalSection 
= new Object();
InBlock.gif
InBlock.gif
InBlock.gif                
// Set the disposing flag to false
InBlock.gif

InBlock.gif                IsDisposed 
= false;
InBlock.gif
InBlock.gif
InBlock.gif                
unsafe
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif
InBlock.gif                    
// Create an IO Completion Port for Thread Pool use
InBlock.gif
                    GetHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0null, (UInt32) GetMaxConcurrency);
InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif
InBlock.gif                
// Test to make sure the IO Completion Port was created
InBlock.gif

InBlock.gif                
if (GetHandle == 0)
InBlock.gif
InBlock.gif                    
throw new Exception("Unable To Create IO Completion Port");
InBlock.gif
InBlock.gif
InBlock.gif                
// Allocate and start the Minimum number of threads specified
InBlock.gif

InBlock.gif                Int32 iStartingCount 
= GetCurThreadsInPool;
InBlock.gif
InBlock.gif        
InBlock.gif
InBlock.gif                ThreadStart tsThread 
= new ThreadStart(IOCPFunction);
InBlock.gif
InBlock.gif                
for (Int32 iThread = 0; iThread < GetMinThreadsInPool; ++iThread)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif
InBlock.gif                    
// Create a thread and start it
InBlock.gif

InBlock.gif                    Thread thThread 
= new Thread(tsThread);
InBlock.gif
InBlock.gif                    thThread.Name 
= "IOCP " + thThread.GetHashCode();
InBlock.gif
InBlock.gif                    thThread.Start();
InBlock.gif
InBlock.gif
InBlock.gif                    
// Increment the thread pool count
InBlock.gif

InBlock.gif                    IncCurThreadsInPool();
InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
throw new Exception("Unhandled Exception");
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
~IOCPThreadPool()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            
if (!IsDisposed)
InBlock.gif
InBlock.gif                Dispose();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
// Flag that we are disposing this object
InBlock.gif

InBlock.gif                IsDisposed 
= true;
InBlock.gif
InBlock.gif
InBlock.gif                
// Get the current number of threads in the pool
InBlock.gif

InBlock.gif                Int32 iCurThreadsInPool 
= GetCurThreadsInPool;
InBlock.gif
InBlock.gif
InBlock.gif                
// Shutdown all thread in the pool
InBlock.gif

InBlock.gif                
for (Int32 iThread = 0; iThread < iCurThreadsInPool; ++iThread)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
unsafe
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        
bool bret = PostQueuedCompletionStatus(GetHandle, 4, (UInt32*) SHUTDOWN_IOCPTHREAD, null);
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif
InBlock.gif                
// Wait here until all the threads are gone
InBlock.gif

InBlock.gif                
while (GetCurThreadsInPool != 0) Thread.Sleep(100);
InBlock.gif
InBlock.gif
InBlock.gif                
unsafe
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif
InBlock.gif                    
// Close the IOCP Handle
InBlock.gif
                    CloseHandle(GetHandle);
InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif        
private void IOCPFunction()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            UInt32 uiNumberOfBytes;
InBlock.gif
InBlock.gif            Int32  iValue;
InBlock.gif
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
while (true)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif
InBlock.gif                    
unsafe
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        System.Threading.NativeOverlapped
* pOv;
InBlock.gif
InBlock.gif
InBlock.gif                        
// Wait for an event
InBlock.gif

InBlock.gif                        GetQueuedCompletionStatus(GetHandle, 
&uiNumberOfBytes, (UInt32*&iValue, &pOv, INIFINITE);
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif                    
// Decrement the number of events in queue
InBlock.gif

InBlock.gif                    DecCurWorkInPool();
InBlock.gif
InBlock.gif
InBlock.gif                    
// Was this thread told to shutdown
InBlock.gif

InBlock.gif                    
if (iValue == SHUTDOWN_IOCPTHREAD)
InBlock.gif
InBlock.gif                        
break;
InBlock.gif
InBlock.gif
InBlock.gif                    
// Increment the number of active threads
InBlock.gif

InBlock.gif                    IncActThreadsInPool();
InBlock.gif
InBlock.gif
InBlock.gif                    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
// Call the user function
InBlock.gif
                        GetUserFunction(iValue);
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif                    
catch(Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
throw ex;
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
// Get a lock
InBlock.gif

InBlock.gif                    Monitor.Enter(GetCriticalSection);
InBlock.gif
InBlock.gif
InBlock.gif                    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        
// If we have less than max threads currently in the pool
InBlock.gif

InBlock.gif                        
if (GetCurThreadsInPool < GetMaxThreadsInPool)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif
InBlock.gif                            
// Should we add a new thread to the pool
InBlock.gif

InBlock.gif                            
if (GetActThreadsInPool == GetCurThreadsInPool)
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
dot.gif{
InBlock.gif
InBlock.gif                                
if (IsDisposed == false)
ExpandedSubBlockStart.gifContractedSubBlock.gif                                
dot.gif{
InBlock.gif
InBlock.gif                                    
// Create a thread and start it
InBlock.gif

InBlock.gif                                    ThreadStart tsThread 
= new ThreadStart(IOCPFunction);
InBlock.gif
InBlock.gif                                    Thread thThread 
= new Thread(tsThread);
InBlock.gif
InBlock.gif                                    thThread.Name 
= "IOCP " + thThread.GetHashCode();
InBlock.gif
InBlock.gif                                    thThread.Start();
InBlock.gif
InBlock.gif
InBlock.gif                                    
// Increment the thread pool count
InBlock.gif

InBlock.gif                                    IncCurThreadsInPool();
InBlock.gif
ExpandedSubBlockEnd.gif                                }

InBlock.gif
ExpandedSubBlockEnd.gif                            }

InBlock.gif
ExpandedSubBlockEnd.gif                        }

InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif                    
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
// Relase the lock
InBlock.gif

InBlock.gif                    Monitor.Exit(GetCriticalSection);
InBlock.gif
InBlock.gif
InBlock.gif                    
// Increment the number of active threads
InBlock.gif

InBlock.gif                    DecActThreadsInPool();
InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
catch(Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
string str=ex.Message;
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
// Decrement the thread pool count
InBlock.gif

InBlock.gif            DecCurThreadsInPool();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
//public void PostEvent(Int32 iValue
InBlock.gif
        public void PostEvent(int iValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
// Only add work if we are not disposing
InBlock.gif

InBlock.gif                
if (IsDisposed == false)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif
InBlock.gif                    
unsafe
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        
// Post an event into the IOCP Thread Pool
InBlock.gif

InBlock.gif                        PostQueuedCompletionStatus(GetHandle, 
4, (UInt32*) iValue, null);
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
// Increment the number of item of work
InBlock.gif

InBlock.gif                    IncCurWorkInPool();
InBlock.gif
InBlock.gif
InBlock.gif                    
// Get a lock
InBlock.gif

InBlock.gif                    Monitor.Enter(GetCriticalSection);
InBlock.gif
InBlock.gif
InBlock.gif                    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        
// If we have less than max threads currently in the pool
InBlock.gif

InBlock.gif                        
if (GetCurThreadsInPool < GetMaxThreadsInPool)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif
InBlock.gif                            
// Should we add a new thread to the pool
InBlock.gif

InBlock.gif                            
if (GetActThreadsInPool == GetCurThreadsInPool)
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
dot.gif{
InBlock.gif
InBlock.gif                                
if (IsDisposed == false)
ExpandedSubBlockStart.gifContractedSubBlock.gif                                
dot.gif{
InBlock.gif
InBlock.gif                                    
// Create a thread and start it
InBlock.gif

InBlock.gif                                    ThreadStart tsThread 
= new ThreadStart(IOCPFunction);
InBlock.gif
InBlock.gif                                    Thread thThread 
= new Thread(tsThread);
InBlock.gif
InBlock.gif                                    thThread.Name 
= "IOCP " + thThread.GetHashCode();
InBlock.gif
InBlock.gif                                    thThread.Start();
InBlock.gif
InBlock.gif
InBlock.gif                                    
// Increment the thread pool count
InBlock.gif

InBlock.gif                                    IncCurThreadsInPool();
InBlock.gif
ExpandedSubBlockEnd.gif                                }

InBlock.gif
ExpandedSubBlockEnd.gif                            }

InBlock.gif
ExpandedSubBlockEnd.gif                        }

InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
// Release the lock
InBlock.gif

InBlock.gif                    Monitor.Exit(GetCriticalSection);
InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
throw e;
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
throw new Exception("Unhandled Exception");
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
ExpandedSubBlockEnd.gif        }
  
InBlock.gif
InBlock.gif        
public void PostEvent()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
// Only add work if we are not disposing
InBlock.gif

InBlock.gif                
if (IsDisposed == false)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif
InBlock.gif                    
unsafe
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        
// Post an event into the IOCP Thread Pool
InBlock.gif

InBlock.gif                        PostQueuedCompletionStatus(GetHandle, 
0nullnull);
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
// Increment the number of item of work
InBlock.gif

InBlock.gif                    IncCurWorkInPool();
InBlock.gif
InBlock.gif
InBlock.gif                    
// Get a lock
InBlock.gif

InBlock.gif                    Monitor.Enter(GetCriticalSection);
InBlock.gif
InBlock.gif
InBlock.gif                    
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
InBlock.gif                        
// If we have less than max threads currently in the pool
InBlock.gif

InBlock.gif                        
if (GetCurThreadsInPool < GetMaxThreadsInPool)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif
InBlock.gif                            
// Should we add a new thread to the pool
InBlock.gif

InBlock.gif                            
if (GetActThreadsInPool == GetCurThreadsInPool)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
dot.gif{
InBlock.gif
InBlock.gif                                
if (IsDisposed == false)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif                                
dot.gif{
InBlock.gif
InBlock.gif                                    
// Create a thread and start it
InBlock.gif

InBlock.gif                                    ThreadStart tsThread 
= new ThreadStart(IOCPFunction);
InBlock.gif
InBlock.gif                                    Thread thThread 
= new Thread(tsThread);
InBlock.gif
InBlock.gif                                    thThread.Name 
= "IOCP " + thThread.GetHashCode();
InBlock.gif
InBlock.gif                                    thThread.Start();
InBlock.gif
InBlock.gif
InBlock.gif                                    
// Increment the thread pool count
InBlock.gif

InBlock.gif                                    IncCurThreadsInPool();
InBlock.gif
ExpandedSubBlockEnd.gif                                }

InBlock.gif
ExpandedSubBlockEnd.gif                            }

InBlock.gif
ExpandedSubBlockEnd.gif                        }

InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif
InBlock.gif                    
// Release the lock
InBlock.gif

InBlock.gif                    Monitor.Exit(GetCriticalSection);
InBlock.gif
ExpandedSubBlockEnd.gif                }

InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
throw new Exception("Unhandled Exception");
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
最近有项目要做一个高性能网络服务器,去网络上搜到到的都是C++版本而且是英文或者简单的DEMO,所以自己动手写了C# 的DEMO。 网络上只写接收到的数据,没有说怎么处理缓冲区数据,本DEMO简单的介绍如何处理接收到的数据。简单易用,希望对大家有用. 1、在C#中,不用去面对完成端口的操作系统内核对象,Microsoft已经为我们提供了SocketAsyncEventArgs,它封装了IOCP的使用。请参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1。 2、我的SocketAsyncEventArgsPool使用List对象来存储对客户端来通信的SocketAsyncEventArgs对象,它相当于直接使用内核对象时的IoContext。我这样设计比用堆栈来实现的好处理是,我可以在SocketAsyncEventArgsPool池中找到任何一个与服务器连接的客户,主动向它发信息。而用堆栈来实现的话,要主动给客户发信息,则还要设计一个结构来存储已连接上服务器的客户。 3、对每一个客户端不管还发送还是接收,我使用同一个SocketAsyncEventArgs对象,对每一个客户端来说,通信是同步进行的,也就是说服务器高度保证同一个客户连接上要么在投递发送请求,并等待;或者是在投递接收请求,等待中。本例只做echo服务器,还未考虑由服务器主动向客户发送信息。 4、SocketAsyncEventArgs的UserToken被直接设定为被接受的客户端Socket。 5、没有使用BufferManager ,因为我在初始化时给每一个SocketAsyncEventArgsPool中的对象分配一个缓冲区,发送时使用Arrary.Copy来进行字符拷贝,不去改变缓冲区的位置,只改变使用的长度,因此在下次投递接收请求时恢复缓冲区长度就可以了!如果要主动给客户发信息的话,可以new一个SocketAsyncEventArgs对象,或者在初始化中建立几个来专门用于主动发送信息,因为这种需求一般是进行信息群发,建立一个对象可以用于很多次信息发送,总体来看,这种花销不大,还减去了字符拷贝消耗。 6、测试结果:(在我的笔记本上时行的,我的本本是T420 I7 8G内存) 100客户 100,000(十万次)不间断的发送接收数据(发送接收之间没有Sleep,就一个一循环,不断的发送与接收) 耗时3004.6325 秒完成 总共 10,000,000 一千万次访问 平均每分完成 199,691.6 次发送与接收 平均每秒完成 3,328.2 次发送与接收 整个运行过程中,内存消耗在开始两三分种后就保持稳定不再增涨。 看了一下对每个客户端的延迟最多不超过2秒。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值