Last active
April 19, 2018 06:10
-
-
Save mjs3339/22f0dd8231f2c3117191781561ab6e69 to your computer and use it in GitHub Desktop.
C# Asynchronously Copy from File to File or Stream to Stream
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static Dictionary<int, TimeSpan> BufferSizeTest() | |
{ | |
const int NumberOfTasks = 10; | |
const int IterationsPerTask = 100; | |
const int SourceFileLength = 2 * 1024 * 1024; | |
var BufferSizes = new[] {4096, 80 * 1024, 1 * 1024 * 1024, 10 * 1024 * 1024}; | |
const string sourcePath = @"s:\test\source.bin"; | |
var sw = new Stopwatch(); | |
var tasks = new Task[NumberOfTasks]; | |
var testResults = new Dictionary<int, TimeSpan>(); | |
File.WriteAllBytes(sourcePath, Enumerable.Range(0, SourceFileLength).Select(i => (byte) i).ToArray()); | |
async Task Cta(Stream source, Stream target, int bSize) | |
{ | |
byte[][] Rwb = {new byte[bSize], new byte[bSize]}; | |
int[] bufferLength = {0, 0}; | |
var bufferIndex = 0; | |
var read = source.ReadAsync(Rwb[bufferIndex], 0, Rwb[bufferIndex].Length); | |
Task write = null; | |
while (true) | |
{ | |
await read; | |
bufferLength[bufferIndex] = read.Result; | |
if (bufferLength[bufferIndex] == 0) | |
break; | |
if (write != null) | |
await write; | |
write = target.WriteAsync(Rwb[bufferIndex], 0, bufferLength[bufferIndex]); | |
bufferIndex ^= 1; | |
read = source.ReadAsync(Rwb[bufferIndex], 0, Rwb[bufferIndex].Length); | |
} | |
if (write != null) | |
await write; | |
target.Flush(); | |
} | |
foreach (var BufferSize in BufferSizes) | |
{ | |
sw.Start(); | |
for (var task = 0; task < tasks.Length; task++) | |
{ | |
var destinationPath = $@"s:\test\destination{task}.bin"; | |
tasks[task] = Task.Run(async () => | |
{ | |
using (var source = new FileStream(sourcePath, | |
FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) | |
using (var dest = new FileStream(destinationPath, | |
FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) | |
{ | |
for (var iter = 0; iter < IterationsPerTask; iter++) | |
{ | |
source.Position = dest.Position = 0; | |
await Cta(source, dest, BufferSize); | |
} | |
} | |
}); | |
} | |
Task.WaitAll(tasks); | |
sw.Stop(); | |
sw.Reset(); | |
testResults.Add(BufferSize, sw.Elapsed); | |
} | |
return testResults; | |
} | |
public void CopyTo(string source, string target) | |
{ | |
using (var sourceStream = new FileStream(source, | |
FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) | |
{ | |
using (var targetStream = new FileStream(target, | |
FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) | |
{ | |
CopyTo(sourceStream, targetStream); | |
} | |
} | |
} | |
public void CopyTo(Stream source, Stream target) | |
{ | |
int[] bufferLength = {0, 0}; | |
var bufferIndex = 0; | |
var read = source.BeginRead(ReadWriteBuffer[bufferIndex], 0, ReadWriteBuffer[bufferIndex].Length, null, null); | |
IAsyncResult write = null; | |
while (true) | |
{ | |
read.AsyncWaitHandle.WaitOne(); | |
bufferLength[bufferIndex] = source.EndRead(read); | |
if (bufferLength[bufferIndex] == 0) | |
break; | |
if (write != null) | |
{ | |
write.AsyncWaitHandle.WaitOne(); | |
target.EndWrite(write); | |
} | |
write = target.BeginWrite(ReadWriteBuffer[bufferIndex], 0, bufferLength[bufferIndex], null, null); | |
bufferIndex ^= 1; | |
read = source.BeginRead(ReadWriteBuffer[bufferIndex], 0, ReadWriteBuffer[bufferIndex].Length, null, null); | |
} | |
if (write != null) | |
{ | |
write.AsyncWaitHandle.WaitOne(); | |
target.EndWrite(write); | |
} | |
target.Flush(); | |
} | |
public async Task CopyToAsync(string source, string target) | |
{ | |
using (var sourceStream = new FileStream(source, | |
FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) | |
{ | |
using (var targetStream = new FileStream(target, | |
FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) | |
{ | |
await CopyToAsync(sourceStream, targetStream); | |
} | |
} | |
} | |
public async Task CopyToAsync(Stream source, Stream target) | |
{ | |
int[] bufferLength = {0, 0}; | |
var bufferIndex = 0; | |
var read = source.ReadAsync(ReadWriteBuffer[bufferIndex], 0, ReadWriteBuffer[bufferIndex].Length); | |
Task write = null; | |
while (true) | |
{ | |
await read; | |
bufferLength[bufferIndex] = read.Result; | |
if (bufferLength[bufferIndex] == 0) | |
break; | |
if (write != null) | |
await write; | |
write = target.WriteAsync(ReadWriteBuffer[bufferIndex], 0, bufferLength[bufferIndex]); | |
bufferIndex ^= 1; | |
read = source.ReadAsync(ReadWriteBuffer[bufferIndex], 0, ReadWriteBuffer[bufferIndex].Length); | |
} | |
if (write != null) | |
await write; | |
target.Flush(); | |
} | |
public async Task CopyToAsync2(string source, string target, CancellationToken cancellationToken = new CancellationToken()) | |
{ | |
using (var sourceStream = new FileStream(source, | |
FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) | |
{ | |
using (var targetStream = new FileStream(target, | |
FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) | |
{ | |
await CopyStream(sourceStream, targetStream, 0, cancellationToken); | |
} | |
} | |
} | |
public async Task CopyStream(Stream source, Stream target, long buffsize = 0, CancellationToken cancellationToken = new CancellationToken()) | |
{ | |
int[] bufferLength = {0, 0}; | |
var bufferIndex = 0; | |
IAsyncResult asyncResult = null; | |
while (true) | |
{ | |
bufferLength[bufferIndex] = | |
await source.ReadAsync(ReadWriteBuffer[bufferIndex], | |
0, | |
ReadWriteBuffer[bufferIndex].Length, | |
cancellationToken).ConfigureAwait(false); | |
if (asyncResult != null) | |
{ | |
asyncResult.AsyncWaitHandle.WaitOne(); | |
target.EndWrite(asyncResult); | |
if (!asyncResult.IsCompleted) | |
throw new IOException("Stream write failed."); | |
} | |
if (bufferLength[bufferIndex] <= 0) | |
break; | |
asyncResult = target.BeginWrite(ReadWriteBuffer[bufferIndex], 0, bufferLength[bufferIndex], null, null); | |
bufferIndex ^= 1; | |
} | |
target.Flush(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment