2011-11-17 94 views
2

讀取大JSON字符串時,我使用下面的代碼上線(顯示UI進度對話框)從ASP.Net MVC Web服務讀取JSON字符串間歇性故障。數據可以在1 mb到4 mb之間。MonoDroid的:從Web服務

public static class WebRequestEx 
    { 
     public static string ExecuteRequestReadToEnd(this WebRequest req) 
     { 
      var resp = req.GetResponse(); 
      using (var resps = resp.GetResponseStream()) 
      { 
       StringBuilder sb = new StringBuilder(); 
       // read through the stream loading up the string builder 
       using (var respRdr = new StreamReader(resps)) 
       { 
        //return respRdr.ReadToEnd(); 
        while (!respRdr.EndOfStream) 
        { 
         sb.Append(respRdr.ReadLine()); 
        } 
        return sb.ToString(); 
       } 
      } 
     } 
} 

stacktrace如下。

I/mono (15666): Stacktrace: 
I/mono (15666): 
I/mono (15666): at System.Threading.WaitHandle.set_Handle (intptr) <0x0008b> 
I/mono (15666): at System.Threading.EventWaitHandle..ctor (bool,System.Threading.EventResetMode) <0x00053> 
I/mono (15666): at System.Threading.ManualResetEvent..ctor (bool) <0x0001f> 
I/mono (15666): at (wrapper remoting-invoke-with-check) System.Threading.ManualResetEvent..ctor (bool) <0xffffffff> 
I/mono (15666): at System.Net.WebAsyncResult.get_AsyncWaitHandle() <0x00073> 
I/mono (15666): at System.Net.WebAsyncResult.WaitUntilComplete (int,bool) <0x00033> 
I/mono (15666): at System.Net.WebConnectionStream.Read (byte[],int,int) <0x000b3> 
I/mono (15666): at System.IO.StreamReader.ReadBuffer() <0x00047> 
I/mono (15666): at System.IO.StreamReader.ReadLine() <0x0014b> 
I/mono (15666): at System.WebRequestEx.ExecuteRequestReadToEnd (System.Net.WebRequest) <0x000ab> 

問題是這不會每次都發生,並且是間歇性的。這很糟糕,因爲它會導致整個應用程序凍結,並且進度對話框停滯不前,用戶無法對應用程序執行任何操作。我在調用代碼中有一個try/catch塊,但是這個異常似乎解決了它。

我較早使用ReadToEnd的和這是炸燬間歇以及讓我通過線路切換到讀取線。

堆棧跟蹤不是特別有益,因爲服用點似乎內的ReadLine是想在()。

想法/建議/選擇?

+0

您應該考慮分頁您的數據並批量使用,不建議您一次性下載4MB大小的手機。 –

回答

0

除非您對您的WebRequest有特殊要求,否則您應該使用WebClient

DownloadString和(甚至更好)DownloadStringAsync這樣的方法將會阻止您處理響應位,因爲它很容易分配給影響應用程序性能的內存和臨時字符串。

+0

從doscs看來,WebClient似乎簡單地包裝了WebRequest類。有興趣看看它們在那裏做了哪些優化?沒有得到上述例外。這個標記爲答案現在。 –

+0

是的,它只是*包裝'WebRequest',但它確實*正確*,並且如果不是最佳或錯誤,它將在新版本中進行優化/修復,而不需要您更新代碼。由於這些代碼直接來自Mono(即它是開源的),因此您可以在github上閱讀它 - > https://github.com/mono/mono/blob/mono-2-10/mcs/class/System/System。淨/ WebClient.cs – poupou

+0

poupou,謝謝。你之前碰過這個嗎? http://stackoverflow.com/questions/8216855/monodroid-encoding-ascii-getstring-failing –

0

嘗試使用此一:

public static string ExecuteRequestReadToEnd(this WebRequest req) 
    { 
     var resp = req.GetResponse(); 
     using (var resps = resp.GetResponseStream()) 
     { 
      var buffer = new byte[16 * 1024]; 
      using (var ms = new MemoryStream()) 
      { 
       int read; 
       while ((read = resps.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        ms.Write(buffer, 0, read); 
       } 
       var content = ms.ToArray(); 
       return Encoding.UTF8.GetString(content, 0, content.Length); 
      } 
     } 
    } 
0

你需要增加的MaxArrayLength價值,因爲你的byte []數組返回超過16348大小。您可以爲maxArrayLength設置的最大值再次是Int32的最大數量,它等於2147483647.修改此設置,您的Web服務將能夠在Web服務和客戶端應用程序之間傳輸大量數據。

Web.config,生成客戶端的Web服務引用綁定。

「的最大消息大小配額用於傳入消息(65536)已被超過。爲了增加配額,使用MaxReceivedMessageSize屬性的適當的結合元件上」。

它設定到最大2^31 - 1或2147483647最大32位的數字。

注意transferMode,默認情況下是緩衝。

  • 緩衝區表示請求和響應消息將被緩衝。

爲transferMode其他枚舉:

  • 串流播放這意味着請求和響應消息將被流傳輸,或
  • StreamedRequest其中而響應消息緩存的請求將被流傳輸,或
  • StreamedResponse所述請求消息而將響應消息STR緩衝eamed。

對於那些不知道,Buffered意味着傳輸將整個消息保存在內存緩衝區中,直到傳輸完成。流意味着只有消息頭將被緩衝,而消息體將被公開爲一個流。

更改爲maxReceivedMessageSize從65536到2147483647 - 如果你離開的transferMode =「緩衝」,我們可能會得到另一個錯誤:

對於TransferMode.Buffered,MaxReceivedMessageSize和MAXBUFFERSIZE必須是相同的值。參數名稱:bindingElement

兩個屬性所需要的相同的值,則MaxReceivedMessageSize比MAXBUFFERSIZE大,如果整個消息被緩衝。

你有兩種選擇: 一)更改MAXBUFFERSIZE爲2147483647 B規格)製作的transferMode到:串流播放,StreamedRequest或StreamedResponse。

「決定使用緩衝還是流式傳輸是HTTP傳輸端點的本地決策。對於HTTP傳輸,傳輸模式不會傳播到連接或代理服務器或其他中介。模式並不反映在服務合同的描述中,在生成服務代理後,您可以(允許但不是必需)編輯配置文件,以便使用流傳輸使用的服務來設置傳輸模式。 TCP和命名管道傳輸,傳輸模式被傳播的策略斷言「。 http://msdn.microsoft.com/en-us/library/system.servicemodel.transfermode.aspx