If you are happy to limit your concurrency to the rate of the slowest stream then this is pretty simple and requires no additional buffer, I have written it from memory so might have messed it up a little.
Also it doesn't implement all the overrides needed, things like CanRead, CanSeek and the like are all skipped for simplicity, just the core concurrent writing is done.
using System;
using System.IO;
using System.Threading;
namespace MultiCastStream
{
public class MultiWriteStream : Stream
{
private readonly Stream[] streams;
private AutoResetEvent[] waits;
private readonly IAsyncResult[] results;
public MultiWriteStream(params Stream[] streams)
{
this.streams = (Stream[])streams.Clone();
this.results = new IAsyncResult[this.streams.Length];
}
private void prepWaits()
{
if (waits == null)
{
this.waits = new AutoResetEvent[this.streams.Length];
for(int i= 0; i < this.waits.Length; i++)
{
this.waits[i] = new AutoResetEvent(false);
}
}
else
{
for(int i= 0; i < this.waits.Length; i++)
{
this.waits[i].Reset();
}
}
}
public override void Write (byte[] buffer, int offset, int count)
{
prepWaits();
for( int i = 0; i < this.streams.Length; i++)
{
this.results[i] = streams[i].BeginWrite(
buffer, offset, count, this.Release, waits[i]);
}
WaitHandle.WaitAll(waits);
for( int i = 0; i < this.streams.Length; i++)
{
this.results[i] = this.streams[i].EndWrite(results[i]);
}
}
private void Release(IAsyncResult result)
{
((AutoResetEvent)result.AsyncState).Set();
}
public override void WriteByte (byte value)
{
// no point doing this asynchronously
foreach (Stream s in this.streams)
s.WriteByte (value);
}
protected override void Dispose (bool disposing)
{
base.Dispose (disposing);
if (this.waits != null)
{
foreach (AutoResetEvent w in this.waits)
w.Close();
}
foreach (Stream s in this.streams)
s.Dispose();
}
}
}