2010-07-26 2 views
3

3 스트림을 관리하는 buffermanager를 작성하려고합니다. 전형적인 사용법은 느린 생산자 및 빠른 소비자 일 것입니다. 세 가지 버퍼 뒤에있는 아이디어는 항상 제작자가 쓸 버퍼가 있으며 소비자는 항상 최신 데이터를 가져온다는 것입니다.생산자/소비자, 스트림 버퍼 문제

이제 저는 이미 이것을 가지고 있으며, 그것은 잘 작동합니다. 버퍼는 여전히 데이터를 기록해야하므로 writebuffer가 요구되고 처음으로, 그 소비자 펄스 수 없기

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; 
     } 

    } 
} 

firsttime 검사가 사용된다. 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 

가 지금은 소비자가 뒤에 하나를 지연 괜찮아, 그렇게 할 예정이다. 당신이 볼 수 있듯이 내 첫 번째 문자열을 잃어 버리는 것이 나의 주된 문제이다. 내가 firsttime 체크를 제거하면

  • , 그것은 작동합니다

    다른 문제점이있다. 하지만 그건 내 의견으로해서는 안된다 ...

  • 만약 내가 Thread.Sleep (1); GetWriteBuffer()에서도 작동합니다. 뭔가 이해가 안되네.

계몽에 대해 미리 감사드립니다.

답변

0

문제가 해결되었습니다. 모든 Stream 인스턴스를 byte []로 바꿨습니다. 이제 제대로 작동합니다. 스트림이 작동하지 않는 이유를 모르겠으므로 더 이상 시간을 보내지 않으려 고합니다.

다음은 동일한 문제가있는 사용자를위한 새로운 코드입니다.

/// <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; 
     } 
    } 
} 
+0

왜 4 버퍼입니까? 스왑하려면 읽기 버퍼, 쓰기 버퍼 및 임시 버퍼 만 있으면됩니다. –

+0

펄스와 대기 사이에 동기화가 없습니다. Monitor 클래스는 Pulse 메서드가 호출되었음을 나타내는 상태를 유지 관리하지 않습니다. 따라서 대기중인 스레드가 없을 때 Pulse를 호출하면 Pulse가 호출 된 적이없는 것처럼 대기 블록을 호출하는 다음 스레드가 차단됩니다. –