Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active April 19, 2018 06:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/22f0dd8231f2c3117191781561ab6e69 to your computer and use it in GitHub Desktop.
Save mjs3339/22f0dd8231f2c3117191781561ab6e69 to your computer and use it in GitHub Desktop.
C# Asynchronously Copy from File to File or Stream to Stream
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