Amazon.EC2.Import.ImageFileParts.FetchNextPartForUpload C# (CSharp) Method

FetchNextPartForUpload() private method

Returns the next part to be uploaded, with its data loaded into the supplied buffer.
We want to serialize read access to the image file stream so that we do not 'thrash' or encounter problems with a non-seekable stream, but at the same time parallelize the part uploads. Reading the data prior to returning the part instance data satisfies this requirement. If an error occurs during a part upload, we currently cease yielding parts to all workers, causing them to expire cleanly 'asap'. This strategy allows us to change to a 'greedy' approach in future where we simply skip over the part in error and do as much uploading as we can before exit.
private FetchNextPartForUpload ( Stream imageFileStream, byte &buffer ) : ImageFilePart
imageFileStream Stream The stream wrapping the image file.
buffer byte Buffer into which the part data will be read.
return ImageFilePart
        internal ImageFilePart FetchNextPartForUpload(Stream imageFileStream, ref byte[] buffer)
        {
            ImageFilePart nextPart = null;
            try
            {
                lock (_syncLock)
                {
                    if (_failedUploads > 0)  // ensures all workers quit asap
                        return null;

                    if (_nextPartForUpload < PartInstances.Count)
                    {
                        nextPart = PartInstances[_nextPartForUpload];
                        var offset = 0;
                        var bytesRemaining = (int)nextPart.ByteRange.Extent;
                        while (bytesRemaining > 0)
                        {
                            var bytesRead = imageFileStream.Read(buffer, offset, bytesRemaining);
                            if (bytesRead > 0)
                            {
                                offset += bytesRead;
                                bytesRemaining -= bytesRead;
                            }
                            else
                            {
                                throw new InvalidOperationException("Encountered unexpected end of stream");
                            }
                        }

                        _nextPartForUpload++;
                    }
                }
            }
            catch
            {
                Interlocked.Increment(ref _failedUploads);
            }
            return nextPart;
        }