예제 #1
0
        public override ValueTask <int> ReadAsync(Memory <byte> destination, CancellationToken cancellationToken)
        {
            if (!CanRead)
            {
                ThrowHelper.ThrowNotSupportedException_UnreadableStream();
            }

            if (CanSeek)
            {
                // This implementation updates the file position after the operation completes, rather than before.
                // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations.
                ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this);
                return(rats.QueueRead(destination, cancellationToken));
            }

            return(RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken));
        }
예제 #2
0
        public override ValueTask <int> ReadAsync(Memory <byte> destination, CancellationToken cancellationToken = default)
        {
            if (!CanSeek)
            {
                return(RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken));
            }

            if (LengthCachingSupported && _length >= 0 && Volatile.Read(ref _filePosition) >= _length)
            {
                // We know for sure that the file length can be safely cached and it has already been obtained.
                // If we have reached EOF we just return here and avoid a sys-call.
                return(ValueTask.FromResult(0));
            }

            // This implementation updates the file position before the operation starts and updates it after incomplete read.
            // This is done to keep backward compatibility for concurrent reads.
            // It uses Interlocked as there can be multiple concurrent incomplete reads updating position at the same time.
            long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length;

            (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, readOffset, cancellationToken, this);
            return(vts != null
                ? new ValueTask <int>(vts, vts.Version)
                : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException <int>(HandleIOError(readOffset, errorCode)));
        }