无缓存高效流(NoCacheStream)
场景:某个方法需要写入流,另一个方法需要将刚写入流的内容读取再处理,整个过程是一次性无需缓存的情况下,可以不使用MemoryStream,那个会占内存,同时由于MemoryStream容量的不固定,扩容的过程也会对性能产生影响。为了可以提供高效的流读写性能,设计一个无缓存流。
此流的写入和读取必须分为2个不同的线程,否则将无法正常工作,推荐写入使用后台线程,而读取使用当前线程,即直接当前线程使用该流对象(读取或返回)。
此流的写入是基于读取的,如果没有读取,写入将无限等待,直到有读取动作,获取读取方缓存,直接往读取方缓存数组中写入。
/// <summary> /// Written in reading /// </summary> public class NoCacheStream : Stream { private ManualResetEvent enablewrite = new ManualResetEvent(false); private AutoResetEvent enableread = new AutoResetEvent(false); private volatile byte[] innerbuffer; private int num, inneroffset, innercount; private bool isend; 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() { throw new NotImplementedException(); } public override long Length { get { throw new NotImplementedException(); } } public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public override int Read(byte[] buffer, int offset, int count) { if (isend) return 0; innerbuffer = buffer; inneroffset = offset; innercount = count; num = 0; enablewrite.Set(); // allow write enableread.WaitOne(); // wait to read return num; } public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } public override void Write(byte[] buffer, int offset, int count) { if (isend) return; enablewrite.WaitOne();//wait read method signal while (count >= innercount) { Array.Copy(buffer, offset, innerbuffer, inneroffset, innercount); offset += innercount; count -= innercount; num += innercount; enablewrite.Reset();//block write enableread.Set();//allow read enablewrite.WaitOne();//wait to write } if (count > 0) { Array.Copy(buffer, offset, innerbuffer, inneroffset, count); inneroffset += count; innercount -= count; num += count; } } /// <summary> /// End of read-write /// </summary> public void End() { isend = true; enableread.Set(); } }