MemoryStream имеет один поток для записи, а другой для чтения
Вот как я пишу в поток, а затем читаю из него, используя 1 поток:
System.IO.MemoryStream ms = new System.IO.MemoryStream();
// write to it
ms.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7 }, 0, 7);
// go to the begining
ms.Seek(0, System.IO.SeekOrigin.Begin);
// now read from it
byte[] myBuffer = new byte[7];
ms.Read(myBuffer, 0, 7);
Теперь мне было интересно, можно ли записать поток памяти из одного потока и прочитать этот поток из отдельного потока.
2 ответа
Вы не можете использовать поток с возможностью одновременного поиска из 2 потоков, так как поток заполнен. например, NetworkStream имеет 2 канала, один для чтения и один для записи, и поэтому не может поддерживать поиск.
Если вам нужны возможности поиска, вам нужно создать 2 потока: один для чтения и один для записи соответственно. В противном случае вы можете просто создать новый тип потока, который позволяет чтение и запись из основного потока памяти, используя эксклюзивный доступ к базовому потоку и восстанавливая его позицию записи / чтения. Примитивным примером этого будет:
class ProducerConsumerStream : Stream
{
private readonly MemoryStream innerStream;
private long readPosition;
private long writePosition;
public ProducerConsumerStream()
{
innerStream = new MemoryStream();
}
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return true; } }
public override void Flush()
{
lock (innerStream)
{
innerStream.Flush();
}
}
public override long Length
{
get
{
lock (innerStream)
{
return innerStream.Length;
}
}
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
lock (innerStream)
{
innerStream.Position = readPosition;
int red = innerStream.Read(buffer, offset, count);
readPosition = innerStream.Position;
return red;
}
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
lock (innerStream)
{
innerStream.Position = writePosition;
innerStream.Write(buffer, offset, count);
writePosition = innerStream.Position;
}
}
}
Если кто-то все еще ищет решения этой проблемы, приведенный ниже код довольно прост и, похоже, отлично работает для одновременного чтения/записи из двух разных потоков.
public class RWMemoryStream : MemoryStream
{
private long readPosition;
private long writePosition;
private readonly object lockStream = new object();
public override void Write(byte[] buffer, int offset, int count)
{
lock (lockStream)
{
Position = writePosition;
base.Write(buffer, offset, count);
writePosition = Position;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int result;
lock (lockStream)
{
Position = readPosition;
result = base.Read(buffer, offset, count);
readPosition += result;
}
return result;
}
}