Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 生产者/消费者,流缓冲区问题_C#_Stream_Buffer - Fatal编程技术网

C# 生产者/消费者,流缓冲区问题

C# 生产者/消费者,流缓冲区问题,c#,stream,buffer,C#,Stream,Buffer,我正在尝试编写一个管理3个流的buffermanager。典型的用法是缓慢的生产者和快速的消费者。这三个缓冲区背后的想法是,生产者总是有一个缓冲区要写入,消费者总是得到最新生成的数据 现在我已经有了这个,它可以正常工作了 namespace YariIfStream { /// <summary> /// A class that manages three buffers used for IF data streams /// </summary&

我正在尝试编写一个管理3个流的buffermanager。典型的用法是缓慢的生产者和快速的消费者。这三个缓冲区背后的想法是,生产者总是有一个缓冲区要写入,消费者总是得到最新生成的数据

现在我已经有了这个,它可以正常工作了

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一样。