2012-09-04 55 views
2

我寫了以下方法從一般流中讀取數據。在我的電腦上它將成爲一款MemoryStream,在現實世界中,它將成爲一個網絡流。流讀取與等待異步

public async void ReadAsync() 
    { 
     byte[] data = new byte[1024]; 
     int numBytesRead = await _stream.ReadAsync(data, 0, 1024); 

     // Process data ... 

     // Read again. 
     ReadAsync(); 
    } 

這裏的想法是,數據獲取回調處理,然後回調應該生成一個新的閱讀器線程(和殺老)。然而,這並不會發生。我得到一個StackOverflowException。

我在做什麼錯?

回答

11

你有一個永無止境的recursion

你永遠在調用ReadAsync()並永遠不會從方法返回(因此打破了無限遞歸)。

一個可能的解決方案是:

public async void ReadAsync() 
{ 
    byte[] data = new byte[1024]; 
    int numBytesRead = await _stream.ReadAsync(data, 0, 1024); 

    // Process data ... 

    // Read again. 
    if(numBytesRead > 0) 
    { 
     ReadAsync(); 
    } 
} 

要理解遞歸更好,check this

+0

是不是執行暫停在await上,並且該方法的其餘部分用作回調?因此,在回調中調用ReadAsync。如果numBytesRead爲0,那麼我將永遠無法讀取更多的流。我想繼續收聽傳入的數據。 – kasperhj

+0

@lejon,這是一個延續塊,是的。任務完成後,您將在等待部分後返回。但是,你會再次立即調用「'ReadAsync'」。如果'numBytesRead'爲零,那麼您再也無法阻止您再次嘗試讀取。說得通?如果您想通過網絡等待傳入數據,那是另一個問題。 –

+0

是的。這很有道理。感謝您指出了這一點。那麼我將如何去等待傳入的數據呢? – kasperhj

2

你至少需要檢查是否存在流數據,重複操作或您的遞歸永遠不會停止

// Read again. 
if(numBytesRead != 0) 
    ReadAsync(); 
7

沒有線程這裏直接參與(見我的介紹到async/await)。

您的StackOverflowException是由於遞歸導致(通常是)太深。只需重新編寫迭代的方法:

public async Task ReadAsync() 
{ 
    byte[] data = new byte[1024]; 

    while (true) 
    { 
    int numBytesRead = await _stream.ReadAsync(data, 0, 1024); 
    if (numBytesRead == 0) 
     return; 

    // Process data ... 
    } 
} 
+0

現在不再是異步了,如果是這樣的話,不是? – Frederic

+0

@Frederic:不確定你的意思。正如方法簽名清楚顯示的那樣,它仍然是「異步」。 –