2017-08-29 89 views
-7

请随意创建一个Windows窗体应用程序。重现错误禁用网络连接并运行代码。它会在每1秒后尝试重新连接。在4-5次尝试启用网络连接并进入调试模式后,您会注意到即使提取产品,Reconnect()方法也被调用4-5次。一旦产品被提取,为什么它会一次又一次地调用Reconnect()方法?Winform递归循环 - 一次又一次调用方法

 string apiUrl = "https://api.gdax.com/products"; 
     string json; 

     private void Form1_Load(object sender, EventArgs e) 
     {    
      try 
      {     
       if (FillProducts()) // product need first 
       { 
       } 
      } 
      catch (WebException ex) 
      { 
       ReconnectOnError(ex); 
      } 
     } 
     private bool FillProducts() 
     { 
      bool isDone = false; 
      try 
      { 
       json = GetGDXJSONData(apiUrl); 
       JsonSerializer serializer = new JsonSerializer(); 
       DataTable dt = (System.Data.DataTable)Newtonsoft.Json.JsonConvert.DeserializeObject(json, (typeof(System.Data.DataTable))); 

       count = dt.Rows.Count; 

       if (count > 0) 
        isDone = true; 
      } 
      catch (Exception ex) 
      {    
       isDone = false; 
       ReconnectOnError(ex); 
      } 
      return isDone; 
     } 

     int count = 0; 
     private void ReconnectOnError(Exception errorMessage) 
     { 
      try 
      { 
       Thread.Sleep(1000); 
       if (count < 1) 
       { 
        FillProducts();  // it comes on this point again and again even the count is greater than 1 
        Reconnect(); 
       } 
       else 
       { 
        Reconnect(); 
       } 
      } 
      catch (WebException ex) 
      { 
       ReconnectOnError(ex); 
      } 
     } 

     private void Reconnect() 
     { 
      // why this is called the number of times the attempt was made to fill the products? 
     }  

     private string GetGDXJSONData(string apiUrl) 
     { 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl); 

      request.Method = "GET"; 
      request.ContentType = "application/json"; 
      request.UserAgent = "gdax-node-client"; 
      request.Accept = "application/json"; 

      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
      string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); 

      return responseString; 
     } 
    } 

编辑 - 这是一个示例代码和我做很多的重新连接()方法的事情,一旦产品有牵强。 另外,如果错误发生在产品被提取后,则不要获得产品,只需调用Reconnect()方法,这就是其他原因。

编辑2 - 请不要仅仅通过查看代码来回复。如果您创建了一个表单并自己运行,并且可以自己查看错误,请告知如何解决此问题。

更新 - 我知道我进入了无限次迭代。我想这和现在的作品:

string apiUrl = "https://api.gdax.com/products"; 
    string json; 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     if (FillProducts()) // product need first 
     { 
     } 
    } 

    bool isOk = false; 
    private string GetGDAXProducts() 
    { 
     try 
     { 
      json = GetGDXJSONData(apiUrl); 
      return json; 
     } 
     catch (Exception ex) 
     {    
      return "-1"; 
     } 
    } 

    int count = 0; 
    private bool FillProducts() 
    { 
     bool isDone = false; 
     string retVal = GetGDAXProducts(); 

     while (retVal == "-1") 
     { 
      retVal = GetGDAXProducts(); 
     } 

     if (retVal != "-1") 
     { 
      JsonSerializer serializer = new JsonSerializer(); 
      DataTable dt = (System.Data.DataTable)Newtonsoft.Json.JsonConvert.DeserializeObject(json, (typeof(System.Data.DataTable))); 

      count = dt.Rows.Count; 

      if (count > 0) 
       isDone = true; 
     } 

     return isDone; 
    } 

    private string GetGDXJSONData(string apiUrl) 
    { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl); 

     request.Method = "GET"; 
     request.ContentType = "application/json"; 
     request.UserAgent = "gdax-node-client"; 
     request.Accept = "application/json"; 

     HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
     string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); 

     return responseString; 
    } 
+2

其归因于其他部分'如果(计数<0)' –

+0

再次fillproducts后调用它... – Proxytype

+0

我不得不这样做。它不是在该行未来虽然。如果你运行代码,你会看到它调用FillProducts();重新连接();一次又一次,即当没有互联网时第一次尝试重新连接的次数 – user1254053

回答

1

这是因为如果没有网络连接,然后调用API的URL连接失败,并在您catch块,您正在尝试重新连接

 catch (Exception ex) 
     {    
      isDone = false; 
      ReconnectOnError(ex); 
     } 
+0

是的我试图重新连接,但是我的问题是一旦互联网恢复,为什么它仍然会调用4-5倍的Reconnect()方法? – user1254053

0

enter image description here

当没有互联网connection.Count变量总是零。

+0

请点击“在这里输入图片描述”链接 –

1

你有一个无意的循环在这里:

如果FillProducts失败,它会调用自身...

  1. 迭代:FP失败
  2. 迭代:FP调用ReconnectOnEx调用FP,这再次失败
  3. 迭代:FP调用ReconnectOnEx调用FP调用ReconnectOnEx ...

n。迭代:....调用成功的FP 并返回

现在整个堆栈将展开,每次迭代调用Reconnect

private bool FillProducts() 
    { 
     bool isDone = false; 
     try 
     { 
      /* ... Fails if no connection ... */ 
     } 
     catch (Exception ex) 
     {    
      isDone = false; 
      ReconnectOnError(ex); // ==> BLOCKS !! 
     } 
     return isDone; 
    } 

    int count = 0; 
    private void ReconnectOnError(Exception errorMessage) 
    { 
     try 
     { 
      Thread.Sleep(1000); 
      if (count < 1) 
      { 
       FillProducts();  // <== Will result in another call to this method. Returns on 1st Succeeding call to FillProducts. 
       Reconnect();  // <== Will be called as soon as FillProducts returns. 
      } 
      else 
      { 
       Reconnect(); 
      } 
     } 
     catch (WebException ex) 
     { 
      ReconnectOnError(ex); 
     } 
    } 

为了避免这种情况,你可以移动的 “重试” 的逻辑到FillProducts方法:

private bool FillProducts() 
    { 
     // To prevent waiting forever ... 
     int retryCount = 10; 

     bool isDone = false; 
     while (!isDone && (retryCount-- > 0)) 
     { 
      try 
      { 
       /* ... Fails if no connection ... */ 

       // OnSuccess=> 
       isDone = true; // will break the loop. 
      } 
      catch (Exception ex) // You should actually catch a more specific Exception here 
           // ... but that's a different question. 
      {    
       isDone = false; 
       // Just omit this! >>> ReconnectOnError(ex); // ==> BLOCKS !! 
       // If you want, you can add a little delay here ... 
       Thread.Sleep(1000); 
       // From your code, I guess this has to be called on failure ... 
       Reconnect(); 
      } 
     } 
     return isDone; 
    } 

其他一些点来考虑:

  1. 你不应该在GUI线程上做网络I/O。您的GUI可能无法响应。考虑使用异步/等待(任务异步模式)

  2. 捕捉Exception可能不是最好的主意。你应该捕捉最具体的异常,并让其余的通过调用者处理。