System.IO.BufferedStream.WriteToUnderlyingStreamAsync C# (CSharp) Méthode

WriteToUnderlyingStreamAsync() private méthode

BufferedStream should be as thin a wrapper as possible. We want WriteAsync to delegate to WriteAsync of the underlying _stream rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream to affect the semantics of the stream it wraps as little as possible.
private WriteToUnderlyingStreamAsync ( byte array, int offset, int count, CancellationToken cancellationToken, Task semaphoreLockTask ) : Task
array byte
offset int
count int
cancellationToken CancellationToken
semaphoreLockTask Task
Résultat Task
        private async Task WriteToUnderlyingStreamAsync(byte[] array, int offset, int count,
                                                        CancellationToken cancellationToken,
                                                        Task semaphoreLockTask)
        {
            Debug.Assert(array != null);
            Debug.Assert(offset >= 0);
            Debug.Assert(count >= 0);
            Debug.Assert(array.Length - offset >= count);
            Debug.Assert(_stream != null);
            Debug.Assert(_stream.CanWrite);
            Debug.Assert(_bufferSize > 0);
            Debug.Assert(semaphoreLockTask != null);

            // See the LARGE COMMENT in Write(..) for the explanation of the write buffer algorithm.

            await semaphoreLockTask.ConfigureAwait(false);
            try
            {

                // The buffer might have been changed by another async task while we were waiting on the semaphore.
                // However, note that if we recalculate the sync completion condition to TRUE, then useBuffer will also be TRUE.

                if (_writePos == 0)
                    ClearReadBufferBeforeWrite();

                int totalUserBytes;
                bool useBuffer;
                checked
                {  // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early:
                    totalUserBytes = _writePos + count;
                    useBuffer = (totalUserBytes + count < (_bufferSize + _bufferSize));
                }

                if (useBuffer)
                {
                    WriteToBuffer(array, ref offset, ref count);

                    if (_writePos < _bufferSize)
                    {
                        Debug.Assert(count == 0);
                        return;
                    }

                    Debug.Assert(count >= 0);
                    Debug.Assert(_writePos == _bufferSize);
                    Debug.Assert(_buffer != null);

                   
                    await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false);
                    _writePos = 0;

                    WriteToBuffer(array, ref offset, ref count);

                    Debug.Assert(count == 0);
                    Debug.Assert(_writePos < _bufferSize);

                }
                else
                {  // if (!useBuffer)
                    // Write out the buffer if necessary.
                    if (_writePos > 0)
                    {
                        Debug.Assert(_buffer != null);
                        Debug.Assert(totalUserBytes >= _bufferSize);

                        // Try avoiding extra write to underlying stream by combining previously buffered data with current user data:
                        if (totalUserBytes <= (_bufferSize + _bufferSize) && totalUserBytes <= MaxShadowBufferSize)
                        {
                            EnsureShadowBufferAllocated();
                            Buffer.BlockCopy(array, offset, _buffer, _writePos, count);

                            await _stream.WriteAsync(_buffer, 0, totalUserBytes, cancellationToken).ConfigureAwait(false);
                            _writePos = 0;
                            return;
                        }

                        await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false);
                        _writePos = 0;
                    }

                    // Write out user data.
                    await _stream.WriteAsync(array, offset, count, cancellationToken).ConfigureAwait(false);
                }
            }
            finally
            {
                SemaphoreSlim sem = LazyEnsureAsyncActiveSemaphoreInitialized();
                sem.Release();
            }
        }