C# 生产者/消费者,流缓冲区问题
我正在尝试编写一个管理3个流的buffermanager。典型的用法是缓慢的生产者和快速的消费者。这三个缓冲区背后的想法是,生产者总是有一个缓冲区要写入,消费者总是得到最新生成的数据 现在我已经有了这个,它可以正常工作了C# 生产者/消费者,流缓冲区问题,c#,stream,buffer,C#,Stream,Buffer,我正在尝试编写一个管理3个流的buffermanager。典型的用法是缓慢的生产者和快速的消费者。这三个缓冲区背后的想法是,生产者总是有一个缓冲区要写入,消费者总是得到最新生成的数据 现在我已经有了这个,它可以正常工作了 namespace YariIfStream { /// <summary> /// A class that manages three buffers used for IF data streams /// </summary&
namespace YariIfStream
{
/// <summary>
/// A class that manages three buffers used for IF data streams
/// </summary>
public class YariIFStream
{
private Stream writebuf; ///<value>The stream used for writing</value>
private Stream readbuf; ///<value>The stream used for reading</value>
private Stream swapbuf; ///<value>The stream used for swapping</value>
private bool firsttime; ///<value>Boolean used for checking if it is the first time a writebuffers is asked</value>
private Object sync; ///<value>Object used for syncing</value>
/// <summary>
/// Initializes a new instance of the Yari.YariIFStream class with expandable buffers
/// </summary>
public YariIFStream()
{
sync = new Object();
eerste = true;
writebuf = new MemoryStream();
readbuf = new MemoryStream();
swapbuf = new MemoryStream();
}
/// <summary>
/// Returns the stream with the buffer with new data ready to be read
/// </summary>
/// <returns>Stream</returns>
public Stream GetReadBuffer()
{
lock (sync)
{
Monitor.Wait(sync);
Stream tempbuf = swapbuf;
swapbuf = readbuf;
readbuf = tempbuf;
}
return readbuf;
}
/// <summary>
/// Returns the stream with the buffer ready to be written with data
/// </summary>
/// <returns>Stream</returns>
public Stream GetWriteBuffer()
{
lock (sync)
{
Stream tempbuf = swapbuf;
swapbuf = writebuf;
writebuf = tempbuf;
if (!firsttime)
{
Monitor.Pulse(sync);
}
else
{
firsttime = false;
}
}
//Thread.Sleep(1);
return writebuf;
}
}
}
namespace YariIfStream
{
///
///管理用于IF数据流的三个缓冲区的类
///
公共级YariIFStream
{
私有流writebuf;///用于写入的流
私有流readbuf;///用于读取的流
私有流swapbuf;///用于交换的流
private bool firsttime;///用于检查是否是第一次询问writebuffers
私有对象同步;///用于同步的对象
///
///使用可扩展缓冲区初始化Yari.YariIFStream类的新实例
///
公共YariIFStream()
{
sync=新对象();
eerste=真;
writebuf=新内存流();
readbuf=新内存流();
swapbuf=新内存流();
}
///
///返回带缓冲区的流,其中包含准备读取的新数据
///
///溪流
公共流GetReadBuffer()
{
锁定(同步)
{
监视器。等待(同步);
流tempbuf=swapbuf;
swapbuf=readbuf;
readbuf=tempbuf;
}
返回readbuf;
}
///
///返回缓冲区准备写入数据的流
///
///溪流
公共流GetWriteBuffer()
{
锁定(同步)
{
流tempbuf=swapbuf;
swapbuf=writebuf;
writebuf=tempbuf;
如果(!第一次)
{
监视器。脉冲(同步);
}
其他的
{
第一次=错误;
}
}
//睡眠(1);
返回writebuf;
}
}
}
第一次检查之所以使用,是因为第一次询问writebuffer时,它不能脉冲消费者,因为缓冲区仍然必须用数据写入。当第二次询问writebuffer时,我们可以确保前一个缓冲区包含数据
我有两个线程,一个生产者和一个消费者。
这是我的输出:
prod: uv_hjd`alv cons: N/<]g[)8fV
prod: N/<]g[)8fV cons: 5Ud*tJ-Qkv
prod: 5Ud*tJ-Qkv cons: 4Lx&Z7qqjA
prod: 4Lx&Z7qqjA cons: kjUuVyCa.B
prod: kjUuVyCa.B
prod:uv\u hjd`alv cons:N/我已经解决了我的问题。我用字节[]替换了所有流实例。现在它工作得很好。
不知道为什么流不能工作,不想花更多的时间来弄清楚这一点
下面是针对遇到相同问题的任何人的新代码
/// <summary>
/// This namespace provides a crossthread-, concurrentproof buffer manager.
/// </summary>
namespace YariIfStream
{
/// <summary>
/// A class that manages three buffers used for IF data streams
/// </summary>
public class YariIFStream
{
private byte[] writebuf; ///<value>The buffer used for writing</value>
private byte[] readbuf; ///<value>The buffer used for reading</value>
private byte[] swapbuf; ///<value>The buffer used for swapping</value>
private bool firsttime; ///<value>Boolean used for checking if it is the first time a writebuffers is asked</value>
private Object sync; ///<value>Object used for syncing</value>
/// <summary>
/// Initializes a new instance of the Yari.YariIFStream class with expandable buffers with a initial capacity as specified
/// </summary>
/// <param name="capacity">Initial capacity of the buffers</param>
public YariIFStream(int capacity)
{
sync = new Object();
firsttime = true;
writebuf = new byte[capacity];
readbuf = new byte[capacity];
swapbuf = new byte[capacity];
}
/// <summary>
/// Returns the buffer with new data ready to be read
/// </summary>
/// <returns>byte[]</returns>
public byte[] GetReadBuffer()
{
byte[] tempbuf;
lock (sync)
{
Monitor.Wait(sync);
tempbuf = swapbuf;
swapbuf = readbuf;
}
readbuf = tempbuf;
return readbuf;
}
/// <summary>
/// Returns the buffer ready to be written with data
/// </summary>
/// <returns>byte[]</returns>
public byte[] GetWriteBuffer()
{
byte[] tempbuf;
lock (sync)
{
tempbuf = swapbuf;
swapbuf = writebuf;
writebuf = tempbuf;
if (!firsttime)
{
Monitor.Pulse(sync);
}
else
{
firsttime = false;
}
}
return writebuf;
}
}
}
//
///这个名称空间提供了一个跨线程、防并发的缓冲区管理器。
///
名称空间YariIfStream
{
///
///管理用于IF数据流的三个缓冲区的类
///
公共级YariIFStream
{
专用字节[]writebuf;///用于写入的缓冲区
专用字节[]readbuf;///用于读取的缓冲区
专用字节[]swapbuf;///用于交换的缓冲区
private bool firsttime;///用于检查是否是第一次询问writebuffers
私有对象同步;///用于同步的对象
///
///使用具有指定初始容量的可扩展缓冲区初始化Yari.YariIFStream类的新实例
///
///缓冲区的初始容量
公共YariIFStream(内部容量)
{
sync=新对象();
第一次=正确;
writebuf=新字节[容量];
readbuf=新字节[容量];
swapbuf=新字节[容量];
}
///
///返回包含准备读取的新数据的缓冲区
///
///字节[]
公共字节[]GetReadBuffer()
{
字节[]tempbuf;
锁定(同步)
{
监视器。等待(同步);
tempbuf=swapbuf;
swapbuf=readbuf;
}
readbuf=tempbuf;
返回readbuf;
}
///
///返回准备写入数据的缓冲区
///
///字节[]
公共字节[]GetWriteBuffer()
{
字节[]tempbuf;
锁定(同步)
{
tempbuf=swapbuf;
swapbuf=writebuf;
writebuf=tempbuf;
如果(!第一次)
{
监视器。脉冲(同步);
}
其他的
{
第一次=错误;
}
}
返回writebuf;
}
}
}
为什么有4个缓冲区?交换只需要一个读缓冲区、一个写缓冲区和一个临时缓冲区。脉冲和等待之间没有同步。Monitor类不保持指示已调用Pulse方法的状态。因此,如果您在没有线程等待时调用Pulse,那么调用Wait的下一个线程将阻塞,就好像从未调用过Pulse一样。