Exemplo n.º 1
0
        private static async Task WriteFileAsync(ActionContext context, OverlappedFileStreamResult result)
        {
            var output = context.HttpContext.Response.Body;
            var input  = result.FileStream;

            var readTask  = _readNotStarted;
            var writeTask = _writeNotStarted;

            // Triple buffer so reads and writes never overlap data
            var buffers = new byte[3][];

            for (var i = 0; i < buffers.Length; i++)
            {
                buffers[i] = ArrayPool <byte> .Shared.Rent(BufferSize);
            }

            var cts  = new CancellationTokenSource();
            var step = 1;

            try
            {
                var count = -1;
                do
                {
                    // Wait for last read to complete before reading again
                    count = await readTask;

                    // If last read wasn't the end, submit another read
                    if (count != 0)
                    {
                        var inputBuffer = buffers[(step % buffers.Length)];
                        readTask = input.ReadAsync(inputBuffer, 0, inputBuffer.Length, cts.Token);
                    }

                    // If previous read read something, write it out
                    if (count > 0)
                    {
                        // Wait for last write to complete before writing again
                        await writeTask;

                        var outputBuffer = buffers[((step - 1) % buffers.Length)];
                        writeTask = output.WriteAsync(outputBuffer, 0, count, cts.Token);
                    }

                    step++;
                } while (count != 0);

                // Wait for final write to complete
                await writeTask;
            }
            finally
            {
                // Cancel any pending operations
                cts.Cancel();

                // Return the buffers
                for (var i = 0; i < buffers.Length; i++)
                {
                    ArrayPool <byte> .Shared.Return(buffers[i]);
                }

                // Dispose the input stream
                input.Dispose();
            }
        }
Exemplo n.º 2
0
 public Task ExecuteAsync(ActionContext context, OverlappedFileStreamResult result)
 {
     SetHeadersAndLog(context, result);
     return(WriteFileAsync(context, result));
 }