2014-12-03 64 views
-1

這是一個非常簡單的問題,但我似乎無法想象沒有與別人交談。MemoryStream等到有東西要讀

我需要一個類似於MemoryStream的流,它將在讀取之前異步阻塞,直到有東西需要讀取或超時。

更新: 好的。我放棄了,並且自己寫了Wrapper類,但EndRead總是返回0.請看下面的代碼。 (不提供任務導向的解決方案。)

public class BlockingMemoryStream : MemoryStream 
    { 
     ManualResetEventSlim isReadReady = new ManualResetEventSlim(false); 

     public override void Write(byte[] buffer, int offset, int count) 
     { 
      base.Write(buffer, offset, count); 
      //base.Position = offset; //I do not know if I need this!!!! 
      isReadReady.Set(); 
     } 

     public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) 
     { 
      IAsyncResult result = base.BeginRead(buffer, offset, count, callback, state); 
      return result; 
     } 

     public override int EndRead(IAsyncResult asyncResult) 
     { 
      isReadReady.Wait(/*600000*/); 
      int aa = base.EndRead(asyncResult); 
      return aa; 
     } 
    } 
+0

上下文不清楚或不明顯。它將如何寫入? – 2014-12-03 08:34:38

+0

請看C.Evenhuis的代碼。那個代碼就是我想要避免的。 – Tanya 2014-12-03 08:58:24

+0

如果你真的只想要一個涉及.NET本身的現有實現的答案,我不認爲你會得到這個答案。一個簡單的啓用超時的'Stream'包裝器可以在沒有太多麻煩的情況下實現(目前的答案儘管如此),但我想如果你只對.NET中已經存在的某些東西感興趣,沒有意義。 – 2014-12-03 19:46:46

回答

0

嘗試這樣的事情,這樣做是隻是遍歷並等待,直到有要讀取的對象。

private static readonly MemoryStream _reader; 
    private static object _data; 

    static Program() 
    { 
     _reader = new MemoryStream(); 
    } 

    private static void Main(string[] args) 
    { 
     Task.Run(async delegate() 
     { 
      while (true) 
      { 
       if (_data == null) 
        await Task.Delay(1000); // so the cpu can have rest 
              // you can lower the value of this 
       else 
       { 
        // read here 
        await Task.Delay(1000); 
       } 
      } 
     }); 
    } 
0

如果我理解正確,你想要一個你寫的流,和另一個線程讀取。你可以滾你自己的,即:

public sealed class MyStream : Stream 
{ 
    private readonly MemoryStream underlyingStream = new MemoryStream(); 
    private readonly AutoResetEvent waitHandle = new AutoResetEvent(false); 

    public int Timeout { get; set; } 

    public MyStream() 
    { 
     Timeout = 5000; 
    } 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     // Write to the stream and notify any waiting threads 
     underlyingStream.Write(buffer, offset, count); 
     waitHandle.Set(); 
    } 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     int bytes; 
     while ((bytes = underlyingStream.Read(buffer, offset, count)) == 0) 
     { 
      // 0 bytes read (end of stream), wait Timeout ms for someone to write 
      if (!waitHandle.WaitOne(Timeout)) 
      { 
       throw new TimeoutException(); 
      } 
     } 

     return bytes; 
    } 

    // TODO other mandatory methods 
} 

我寫上面的例子中沒有檢測和Stream實現是不完整的,它只是顯示了您的解決方案可能的方向。如果多個線程從中獲得Read,則可能需要完成大量的Timeout

如果您不喜歡使用等待句柄,您也可以使用TCP回送套接字並使用NetworkStream

+0

謝謝!我已經考慮實現這一點,但我希望在C#中已經有了一些東西。 NetworkStream不太好 - 它需要太多的虛擬可讀文件。 – Tanya 2014-12-03 08:55:23

+0

即使OP願意接受一個非內置的實現,這個答案根本上是錯誤的:當一個Read()操作返回0字節時,這表示Stream的結束。無論你等待多久,在這一點上都不會再有字節數。 – 2014-12-03 19:45:05

+0

@PeterDuniho我很欣賞評論,你是對的,它應該拋出'TimeoutException',我會糾正我的答案。我不認爲這是_fundamentally_ wrong,但我提供了一個定製解決方案的想法和一個內置的。 – 2014-12-03 22:22:12