/// <summary>
        /// The completion callback for when the operation completes. This is
        /// an internal callback that frees the native memory and subsequently
        /// invokes the original caller's completion callback so it can
        /// retrieve the result.
        /// </summary>
        private unsafe void CompletionCallback(
            UInt32 errorCode,
            UInt32 numBytes,
            NativeOverlapped *nativeOverlapped
            )
        {
            // First, free the NativeOverlapped structure and let this
            // IAsyncResult be collectable by the garbage collector
            Overlapped.Free(nativeOverlapped);

            try
            {
                if (errorCode != 0)
                {
                    // Check if an error occurred and record the error if so
                    base.SetAsCompleted(new Win32Exception((Int32)errorCode), false);
                }
                else
                {
                    // No error occurred, so the output buffer must contain the
                    // result!
                    TResult result = (TResult)mOutDeviceBuffer.Target;

                    // The result is going to be an array of bytes, so we need
                    // to resize the array to the exact size so that the Length
                    // property is accurate
                    if ((result != null) && result.GetType().IsArray)
                    {
                        // Only resize if the number of elements initialized in
                        // the array is less than the size of the array itself
                        Type  elementType   = result.GetType().GetElementType();
                        Int64 numElements   = numBytes / Marshal.SizeOf(elementType);
                        Array originalArray = (Array)(object)result;
                        if (numElements < originalArray.Length)
                        {
                            // Create a new array whose size is the number of
                            // initialized elements
                            Array newArray = Array.CreateInstance(elementType,
                                                                  numElements
                                                                  );
                            // Copy the initialized elements from the original
                            // array to the new one
                            Array.Copy(originalArray, newArray, numElements);
                            result = (TResult)(object)newArray;
                        }
                    }

                    // Record the result and call the AsyncCallback method
                    base.SetAsCompleted(result, false);
                }
            }
            finally
            {
                // Make sure that the input and output buffers are unpinned
                mOutDeviceBuffer.Dispose();
                mOutDeviceBuffer = null;  // Allow early GC
            }
        }
Example #2
0
        // This method is called by a thread pool thread when native overlapped I/O completes
        private unsafe void CompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped *nativeOverlapped)
        {
            // Release the native OVERLAPPED structure and
            // let the IAsyncResult object (this) be collectable.
            Overlapped.Free(nativeOverlapped);

            try {
                if (errorCode != 0)
                {
                    // An error occurred, record the Win32 error code
                    base.SetAsCompleted(new Win32Exception((Int32)errorCode), false);
                }
                else
                {
                    // No error occurred, the output buffer contains the result
                    TResult result = (TResult)m_outBuffer.Target;

                    // If the result is an array of values, resize the array
                    // to the exact size so that the Length property is accurate
                    if ((result != null) && result.GetType().IsArray)
                    {
                        // Only resize if the number of elements initialized in the
                        // array is less than the size of the array itself
                        Type  elementType = result.GetType().GetElementType();
                        Int64 numElements = numBytes / Marshal.SizeOf(elementType);
                        Array origArray   = (Array)(Object)result;
                        if (numElements < origArray.Length)
                        {
                            // Create a new array whose size equals the number of initialized elements
                            Array newArray = Array.CreateInstance(elementType, numElements);

                            // Copy the initialized elements from the original array to the new array
                            Array.Copy(origArray, newArray, numElements);
                            result = (TResult)(Object)newArray;
                        }
                    }

                    // Record result and call AsyncCallback method passed to BeginXxx method
                    base.SetAsCompleted(result, false);
                }
            }
            finally {
                // Make sure that the input and output buffers are unpinned
                m_inBuffer.Dispose();
                m_outBuffer.Dispose();
                m_inBuffer = m_outBuffer = null; // Allow early GC
            }
        }