/// <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 } }
// 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 } }