This time to give you a demonstration of the use of IOCP to pass the data between the examples, by the way to tell some details and attention to the place.
Overview: The main use of IOCP's three api,createiocompletionport,postqueuedcompletionstatus,getqueuedcompletionstatus, The first is to create a completion port object, the second is to send data to a port, the third is to accept data, basically with three functions, you can write a simple example using IOCP.
Which completes the port a kernel object, so the creation will cost performance, the CPU has to switch to kernel mode, and once the kernel object is created, we have to remember that when we need to explicitly release its handle, the best practice for releasing unmanaged resources is definitely to use Dispose mode, This blog park has been talked about N times. and generally to get a reference to a kernel object, it is best to use SafeHandle to refer to it, this class can help you manage the reference count, and use it to refer to the kernel object, the code is more robust, if you use pointers to reference kernel objects, create a successful kernel object and copy to the pointer this time If the ThreadAbortException is thrown, the kernel object is leaked, and the SafeHandle to apply the kernel object will not occur ThreadAbortException when the value is assigned. In addition, the SafeHandle class inherits from the CriticalFinalizerObject class and implements the IDispose interface, where the CLR has special care for CriticalFinalizerObject and its subclasses, such as compile-time precedence, The Finalize method of the Finalize class of the CriticalFinalizerObject class is called after the Finalize method of the CriticalFinalizerObject class is invoked. In Win32, the general one handle is-1 or 0-indicates that the handle is invalid, so. NET has a SafeHandle derived class Safehandlezeroorminusoneisinvalid, but this class is an abstract class, To refer to the kernel object or unmanaged object you are using, derive a class from this class and rewrite the Relseas method. In the. NET Framework it has two subclasses that are almost identical, one is the Safefilehandle, the other is Safewaithandle, the former represents the file handle, the latter represents the wait handle, and we use Safefilehandle to refer to the completion Port object directly for convenience.
The prototype of the CreateIoCompletionPort function is as follows [DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern safefilehandle CreateIoCompletionPort (IntPtr filehandle, IntPtr existingcompletionport, IntPtr Completionkey, UINT numberofconcurrentthreads);
The FileHandle parameter represents a handle to be bound on the completion port, such as a socket handle that has been accept.
The Existingcompletionport parameter represents an existing completion port handle, and the first time the completion port is created, it is obvious that the value is passed, so this parameter is defined directly as the IntPtr type. When you create a work thread to request a service for I/O, the handle is associated with the completion port, and the first time the completion port is created, the parameter passes a zero pointer to the O, and the FileHandle parameter passes a pointer of 1.
Completionkey is the completion of the key meaning, it can be any want to pass to the work thread data, the scientific name is called simple handle data, that is, follow the filehandle parameters to go some state data, generally in the socket IOCP program is the socket into, So that the socket handle is CHENGRI on the work line, and the delivery of the next asynchronous operation, such as sending and receiving data, is resumed after receiving the notification and processing of the asynchronous operation completion.
The NumberOfConcurrentThreads parameter represents the maximum number of threads that are allowed to execute concurrently on a completion port. If you pass 0, it means that you have a few CPUs that allow you to have a maximum number of threads, which is also ideal, because a single CPU thread can prevent the thread context from switching. As for the relationship between this value and the number of worker threads created, you should understand how many of your worker threads are not necessarily the number of CPUs. Because your work thread can sometimes block or wait, and if you happen to create a number of CPU threads, there is a wait, because you are allocating the maximum number of CPUs at the same time more than the largest IOCP thread, this is not efficient to maximize. So the general worker thread creates more than the number of CPUs, unless you guarantee that your work thread will not block.
The PostQueuedCompletionStatus function prototype is as follows [DllImport ("Kernel32", CharSet = CharSet.Auto)] private static extern bool Postqueuedc Ompletionstatus (Safefilehandle completionport, uint dwnumberofbytestransferred, IntPtr Dwcompletionkey, INTPTR lpoverlapped); This method is used for the completion of the port delivery customization information, in general, if a handle and completion of the port binding, when there is a data transceiver operation is completed automatically at the same time the worker thread, the work line Chengri GetQueuedCompletionStatus will not block, and continue to go down, To perform the process of receiving an IO operation to complete the notification. And sometimes we need to manually send some messages to worker threads, such as our main thread knows that all the socket handles are closed, the worker thread can quit, we can give the work line Cheng a custom data, the worker thread when it is received to determine whether the exit instructions, and then exit.
The Completionport parameter indicates to which completion port object The message is posted, and the worker thread waiting for the message on the completion port will receive the message. Dwnumberofbytestransferred that you have posted a large number of data, we generally deliver a pointer to an object, in 32-bit system, the int pointer is 4 bytes, directly write 4 o, or use sizeof you pass data, such as sizeof ( INTPTR).
Dwcompletionkey with CreateIoCompletionPort interpretation, is a simple handle data, this example is not used, do not elaborate, directly with IntPtr.Zero fill.