System.IO.StreamOperationsImplementation.ReadAsync_AbstractStream C# (CSharp) Méthode

ReadAsync_AbstractStream() static private méthode

static private ReadAsync_AbstractStream ( Stream stream, Windows.Storage.Streams.IBuffer buffer, UInt32 count, InputStreamOptions options ) : UInt32>.IAsyncOperationWithProgress
stream Stream
buffer Windows.Storage.Streams.IBuffer
count UInt32
options InputStreamOptions
Résultat UInt32>.IAsyncOperationWithProgress
        internal static IAsyncOperationWithProgress<IBuffer, UInt32> ReadAsync_AbstractStream(Stream stream, IBuffer buffer, UInt32 count,
                                                                                              InputStreamOptions options)
        {
            Debug.Assert(stream != null);
            Debug.Assert(stream.CanRead);
            Debug.Assert(buffer != null);
            Debug.Assert(buffer is IBufferByteAccess);
            Debug.Assert(0 <= count);
            Debug.Assert(count <= Int32.MaxValue);
            Debug.Assert(count <= buffer.Capacity);
            Debug.Assert(options == InputStreamOptions.None || options == InputStreamOptions.Partial || options == InputStreamOptions.ReadAhead);
            Contract.EndContractBlock();

            Int32 bytesRequested = (Int32)count;

            // Check if the buffer is our implementation.
            // IF YES: In that case, we can read directly into its data array.
            // IF NO:  The buffer is of unknown implementation. It's not backed by a managed array, but the wrapped stream can only
            //         read into a managed array. If we used the user-supplied buffer we would need to copy data into it after every read.
            //         The spec allows to return a buffer instance that is not the same as passed by the user. So, we will create an own
            //         buffer instance, read data *directly* into the array backing it and then return it to the user.
            //         Note: the allocation costs we are paying for the new buffer are unavoidable anyway, as we we would need to create
            //         an array to read into either way.

            IBuffer dataBuffer = buffer as WindowsRuntimeBuffer;

            if (dataBuffer == null)
                dataBuffer = WindowsRuntimeBuffer.Create((Int32)Math.Min((UInt32)Int32.MaxValue, buffer.Capacity));

            // This operation delegate will we run inside of the returned IAsyncOperationWithProgress:
            Func<CancellationToken, IProgress<UInt32>, Task<IBuffer>> readOperation = async (cancelToken, progressListener) =>
            {
                // No bytes read yet:
                dataBuffer.Length = 0;

                // Get the buffer backing array:
                Byte[] data;
                Int32 offset;
                bool managedBufferAssert = dataBuffer.TryGetUnderlyingData(out data, out offset);
                Debug.Assert(managedBufferAssert);

                // Init tracking values:
                bool done = cancelToken.IsCancellationRequested;
                Int32 bytesCompleted = 0;

                // Loop until EOS, cancelled or read enough data according to options:
                while (!done)
                {
                    Int32 bytesRead = 0;

                    try
                    {
                        // Read asynchronously:
                        bytesRead = await stream.ReadAsync(data, offset + bytesCompleted, bytesRequested - bytesCompleted, cancelToken)
                                                .ConfigureAwait(continueOnCapturedContext: false);

                        // We will continue here on a different thread when read async completed:
                        bytesCompleted += bytesRead;
                        // We will handle a cancelation exception and re-throw all others:
                    }
                    catch (OperationCanceledException)
                    {
                        // We assume that cancelToken.IsCancellationRequested is has been set and simply proceed.
                        // (we check cancelToken.IsCancellationRequested later)
                        Debug.Assert(cancelToken.IsCancellationRequested);

                        // This is because if the cancellation came after we read some bytes we want to return the results we got instead
                        // of an empty cancelled task, so if we have not yet read anything at all, then we can throw cancellation:
                        if (bytesCompleted == 0 && bytesRead == 0)
                            throw;
                    }

                    // Update target buffer:
                    dataBuffer.Length = (UInt32)bytesCompleted;

                    Debug.Assert(bytesCompleted <= bytesRequested);

                    // Check if we are done:
                    done = options == InputStreamOptions.Partial  // If no complete read was requested, any amount of data is OK
                            || bytesRead == 0                         // this implies EndOfStream
                            || bytesCompleted == bytesRequested       // read all requested bytes
                            || cancelToken.IsCancellationRequested;   // operation was cancelled

                    // Call user Progress handler:
                    if (progressListener != null)
                        progressListener.Report(dataBuffer.Length);
                }  // while (!done)

                // If we got here, then no error was detected. Return the results buffer:
                return dataBuffer;
            };  // readOperation

            return AsyncInfo.Run<IBuffer, UInt32>(readOperation);
        }  // ReadAsync_AbstractStream

Usage Example

Exemple #1
0
        public IAsyncOperationWithProgress <IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
        {
            if (buffer == null)
            {
                // Mapped to E_POINTER.
                throw new ArgumentNullException(nameof(buffer));
            }

            if (count < 0 || int.MaxValue < count)
            {
                ArgumentOutOfRangeException ex = new ArgumentOutOfRangeException(nameof(count));
                ex.HResult = __HResults.E_INVALIDARG;
                throw ex;
            }

            if (buffer.Capacity < count)
            {
                ArgumentException ex = new ArgumentException(SR.Argument_InsufficientBufferCapacity);
                ex.HResult = __HResults.E_INVALIDARG;
                throw ex;
            }

            if (!(options == InputStreamOptions.None || options == InputStreamOptions.Partial || options == InputStreamOptions.ReadAhead))
            {
                ArgumentOutOfRangeException ex = new ArgumentOutOfRangeException(nameof(options),
                                                                                 SR.ArgumentOutOfRange_InvalidInputStreamOptionsEnumValue);
                ex.HResult = __HResults.E_INVALIDARG;
                throw ex;
            }

            Stream str = EnsureNotDisposed();

            IAsyncOperationWithProgress <IBuffer, uint> readAsyncOperation;

            switch (_readOptimization)
            {
            case StreamReadOperationOptimization.MemoryStream:
                readAsyncOperation = StreamOperationsImplementation.ReadAsync_MemoryStream(str, buffer, count);
                break;

            case StreamReadOperationOptimization.AbstractStream:
                readAsyncOperation = StreamOperationsImplementation.ReadAsync_AbstractStream(str, buffer, count, options);
                break;

            // Use this pattern to add more optimisation options if necessary:
            //case StreamReadOperationOptimization.XxxxStream:
            //    readAsyncOperation = StreamOperationsImplementation.ReadAsync_XxxxStream(str, buffer, count, options);
            //    break;

            default:
                Debug.Fail("We should never get here. Someone forgot to handle an input stream optimisation option.");
                readAsyncOperation = null;
                break;
            }

            return(readAsyncOperation);
        }
All Usage Examples Of System.IO.StreamOperationsImplementation::ReadAsync_AbstractStream