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文字で問題ありますか?)。このようなもの(この例ではレコードは1つだけです)

80643 | 882168 | 145 | 1 | 3 | 1 | 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、ミラノ・ディッタ: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 A 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

を使用して問題がありましたをお読みください? ReadLineを使用する必要があります。その行はCRLFで終わっていますか?他の方法を使わなければならないのですか?

私の英語のために残念です。私はいくつかの他の情報を与えなければならないかどうか教えてください。ここ

TIA

アレッサンドロ

+0

要求/読み取りがブロックできるだけでなく、非同期のWebRequestでも失敗する可能性があります。根本的な原因は、切断されたネットワークや他の多くの場合です(ネットワークトレースとサーバーイベントログを分析する必要があります)。あなたのコードを新しいスレッドに入れて、タイムアウト後にthread.joinを使って、スレッドが終了したかどうかをテストします。要求が成功しなかった場合は、スレッドを再試行することができます。 – josef

+0

ありがとう@josefこれを実装する方法の例がありますか?あなたはどのタイムアウトを話していますか? –

答えて

0

スレッドと外部のタイムアウト(第2スレッド)でこれを行う方法の未確認コードスニペットである:

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

関連する問題