0

我有用於Windows Mobile 6.5終端的CSharp應用程序(CF2.0)。 我有一個線程,每1.5分鐘嘗試連接到一個PHP WebService。我嘗試用ReadToEnd()方法讀取此PHP WebService的響應。 它可以工作,但有時(隨機)ReadToEnd()上的例程塊。我不知道爲什麼。使用帶有HttpWebResponse塊的StreamReader塊ReadToEnd()

這是代碼:

public static string CallWebServiceProblem(string url, int timeout) 
{ 

    string s = ""; 

    ServicePointManager.DefaultConnectionLimit = 10; 


    _logger.Trace("web service: {0} timeout: {1}", url, timeout); 
    HttpWebRequest wrGETURL = null; 
    try 
    { 
     bool isProblema = url.IndexOf("lsp_r2") >= 0; 
     if (isProblema) 
      _logger.Info("Sono in lsp_r2..."); 

     wrGETURL = (HttpWebRequest)WebRequest.Create(url); 
     wrGETURL.Credentials = CredentialCache.DefaultCredentials; 

     wrGETURL.ReadWriteTimeout = 10000; // Per vedere se sistema un po' i timeout... 
     if (timeout != 0) 
      wrGETURL.Timeout = 3000; // timeout... 

     Stream ojstream = null; 
     StreamReader sr = null; 
     HttpWebResponse httpresponse = null; 

     try 
     { 
      if (isProblema) 
       _logger.Info("lsp_r2: Chiamo GetResponse..."); 

      httpresponse = (HttpWebResponse)wrGETURL.GetResponse(); 

      if (isProblema) 
       _logger.Info("lsp_r2: Chiamo GetResponseStream..."); 

      ojstream = httpresponse.GetResponseStream(); 
      Encoding encode = System.Text.Encoding.GetEncoding("utf-8"); 

      if (isProblema) 
       _logger.Info("lsp_r2: Chiamo StreamReader..."); 

      sr = new StreamReader(ojstream, encode); 

      if (isProblema) 
       _logger.Info("lsp_r2: inizio a leggere"); 

      s = sr.ReadToEnd(); 
      if (isProblema) 
      { 
       _logger.Info("lsp_r2: terminato di leggere " + s.Length + " caratteri"); 
       System.Diagnostics.Debug.WriteLine("lsp_r2: terminato di leggere " + s.Length + " caratteri"); 
#if DEBUG 
       // _logger.Info("lsp_r2: ho letto " + s); 
       System.Diagnostics.Debug.WriteLine("lsp_r2: ho letto " + s); 
#endif 
      } 
     } 
     catch (Exception ex) 
     { 
      _logger.Error("web service: {0} timeout: {1} exception: {2} - {3}", url, timeout, ex.Message, ex.InnerException != null ? ex.InnerException.Message : "??"); 
      throw new Exception(ex.Message); 
     } 
     finally 
     { 

      if (isProblema) 
       _logger.Info("lsp_r2: Concludo..."); 

      if (sr != null) 
      { 
       sr.Close(); 
       sr.Dispose(); 
      } 

      if (ojstream != null) 
      { 
       ojstream.Close(); 
       ojstream.Dispose(); 
      } 

      if (httpresponse != null) 
      { 
       httpresponse.Close(); 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     throw new Exception(ex.Message); 
    } 
    finally 
    { 

    } 

    return s; 

} 

我在申請使用該程序的一些PHP WS,但我有問題只與一個返回很多的字符(可8000多.. )。從WS返回的字符串是一個以CRLF結尾的字符串;值用|分隔和記錄用§(可以是這個ASCII字符是一個問題??)分開。類似的東西(這個例子只有一條記錄)

80643 | 882168 | 145 | 1 | 3 | 1 | 0 | 0 | 0 | 0 | 0 | 2016-04-04 19:43:24 | 1900- 01-01 00:00:00 | 1900-01-01 00:00:00 | 1900-01-01 00:00:00 | 2016-04-04 19:43:42 ||||| 2016-04- 04 09:45:42 | 08:45 1TG GALDINO,8 Milano Ditta:ZEBRE X PROVA()|| Int.pr:Orario Continuato | 2016-04-04 10:45:42 | V LARGA,Ditta:()| LARGA | Int.co:Orario Continuato || 0 | 2016-04-04 08:46:03 | 2016-04-04 19:43:42 | 2 || 0 | 0000-00-00 00:00:00§

當塊occours,在我的日誌我看到「lsp_r2:inizio一個leggere」(在ReadToEnd的前行),我沒有看到lsp_r2:terminato迪leggere(該行的ReadToEnd的AFTER) 。

我曾嘗試使用也像這樣

int totCar = 0; 
while (sr.EndOfStream == false) { 
    int numCar = sr.Peek(); 

    char[] caratteri = new char[numCar]; 

    sr.Read(caratteri, 0, numCar); 

    string newString = new string(caratteri); 
    // Arrivano un sacco di null.. li rimuovo 
    int posNull = newString.IndexOf('\0'); 
    if (posNull >= 0) 
     newString = newString.Substring(0, posNull); 

    s += newString; 
    totCar += newString.Length; 

    // if (isProblema) 
    //  _logger.Info("lsp_r2: letti: " + numCar + " caratteri"); 

} 

但我也使用sr.Read

有問題,也有一些是我不知道的Socket通信,可以阻止閱讀?我應該使用ReadLine,因爲該行以CRLF結束?我必須使用其他方法嗎?

對不起,我的英語。讓我知道如果我必須提供一些其他信息。

TIA

亞歷山德羅

+0

不僅請求/讀取可以阻塞,甚至異步WebRequest可能會失敗。根本原因可能是斷開的網絡和其他許多網絡(您需要分析網絡跟蹤和服務器事件日誌)。我會把你的代碼放在一個新線程中,然後在超時後使用thread.join來測試線程是否完成。如果請求沒有成功,您可以重新嘗試該線程。 – josef

+0

謝謝@josef你有一個例子如何實現這個?你在說什麼超時? –

回答

0

下面是關於如何使用一個線程和外部超時(第二線程)做一個未經檢查的代碼片段:

using System; 
using System.Web; 
using System.Threading; 

public class myWebRequest:IDisposable{ 
    public class myEventArgs:System.EventArgs{ 
     public string msg; 
     public myEventArgs(string s){ 
      msg=s; 
     } 
    } 
    public delegate void myDelegate (myEventArgs args); 

     public myDelegate theDelegate; 

     void onUpdate (myEventArgs arg) 
     { 
      if (theDelegate != null) 
       theDelegate (arg); 
     } 

     Thread myThread = null; 
     Thread watchThread = null; 

    object lockObject = new object(); 
    bool bThreadRunning = false; 

    public myWebRequest(){ 
    } 
    public void Dispose(){ 
     if (watchThread != null) { 
      watchThread.Abort(); 
      watchThread = null; 
     } 
     if (myThread != null) { 
      myThread.Abort(); 
      myThread = null; 
     } 
    } 

    public void startRequest(){ 
     if (myThread != null) { 
      myThread.Abort(); 
      myThread = null; 
     } 
     myThread = new Thread (theThread); 
     myThread.Start(); 

     //start the watch thread 
     if (watchThread != null) { 
      watchThread.Abort(); 
      watchThread = null; 
     } 
     watchThread = new Thread (theWatchThread); 
     watchThread.Start(); 
    } 

    void theWatchThread(){ 
     try{ 
      Thread.Sleep (5000); 
      if (bThreadRunning && myThread != null) { 
       //thread is running, try a join 
       if (myThread.Join (5000)) { 
        //join did work, although thread should have finished 
        myThread.Abort(); 
        myThread = null; 
        bThreadRunning = false; 
        onUpdate(new myEventArgs("failed")); 
       } 
      } 
     }catch(ThreadAbortException ex){ 
     } 
     catch(Exception ex){ 
     } 
    } 

    void theThread(){ 
     string sMsg = ""; 
     try { 
      bThreadRunning=true; 
      //call the possibly blocking function 
      sMsg=myWebRequest.CallWebServiceProblem("url", 4000); 
      onUpdate(new myEventArgs(sMsg)); 
     }catch(ThreadAbortException ex){ 

     } 
     catch (Exception ex) { 

     } 
     bThreadRunning = false; 
    } 

    static string CallWebServiceProblem(string url, int timeout) 
    { 

     string s = ""; 

     ServicePointManager.DefaultConnectionLimit = 10; 


     _logger.Trace("web service: {0} timeout: {1}", url, timeout); 
     HttpWebRequest wrGETURL = null; 
     try 
     { 
      bool isProblema = url.IndexOf("lsp_r2") >= 0; 
      if (isProblema) 
       _logger.Info("Sono in lsp_r2..."); 

      wrGETURL = (HttpWebRequest)WebRequest.Create(url); 
      wrGETURL.Credentials = CredentialCache.DefaultCredentials; 

      wrGETURL.ReadWriteTimeout = 10000; // Per vedere se sistema un po' i timeout... 
      if (timeout != 0) 
       wrGETURL.Timeout = 3000; // timeout... 

      Stream ojstream = null; 
      StreamReader sr = null; 
      HttpWebResponse httpresponse = null; 

      try 
      { 
       if (isProblema) 
        _logger.Info("lsp_r2: Chiamo GetResponse..."); 

       httpresponse = (HttpWebResponse)wrGETURL.GetResponse(); 

       if (isProblema) 
        _logger.Info("lsp_r2: Chiamo GetResponseStream..."); 

       ojstream = httpresponse.GetResponseStream(); 
       Encoding encode = System.Text.Encoding.GetEncoding("utf-8"); 

       if (isProblema) 
        _logger.Info("lsp_r2: Chiamo StreamReader..."); 

       sr = new StreamReader(ojstream, encode); 

       if (isProblema) 
        _logger.Info("lsp_r2: inizio a leggere"); 

       s = sr.ReadToEnd(); 
       if (isProblema) 
       { 
        _logger.Info("lsp_r2: terminato di leggere " + s.Length + " caratteri"); 
        System.Diagnostics.Debug.WriteLine("lsp_r2: terminato di leggere " + s.Length + " caratteri"); 
        #if DEBUG 
        // _logger.Info("lsp_r2: ho letto " + s); 
        System.Diagnostics.Debug.WriteLine("lsp_r2: ho letto " + s); 
        #endif 
       } 
      } 
      catch (Exception ex) 
      { 
       _logger.Error("web service: {0} timeout: {1} exception: {2} - {3}", url, timeout, ex.Message, ex.InnerException != null ? ex.InnerException.Message : "??"); 
       throw new Exception(ex.Message); 
      } 
      finally 
      { 

       if (isProblema) 
        _logger.Info("lsp_r2: Concludo..."); 

       if (sr != null) 
       { 
        sr.Close(); 
        sr.Dispose(); 
       } 

       if (ojstream != null) 
       { 
        ojstream.Close(); 
        ojstream.Dispose(); 
       } 

       if (httpresponse != null) 
       { 
        httpresponse.Close(); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new Exception(ex.Message); 
     } 
     finally 
     { 

     } 

     return s; 

    } 
} 

從表單中使用它:

void doTest(){ 
     myWebRequest theRequest = new myWebRequest(); 
     theRequest.theDelegate += new myWebRequest.myDelegate (onReceive); 
    } 
    void onReceive(myWebRequest.myEventArgs args){ 
     //updateGUI? 
    } 

在onReceive中,您將得到「失敗」或結果。

上面的代碼只是一個框架...

+0

謝謝@josef我會做一些測試。有沒有更簡單的方法爲ReadToEnd添加超時? –

+0

問題是API錯誤,並不總是超時。所以解決方法很難。即使有異步代碼更改,您也可能遇到此類問題。 – josef

相關問題