请随意创建一个Windows窗体应用程序。要重现错误,请禁用网络连接并运行代码。它会在每1秒后尝试重新连接。在4-5次尝试启用网络连接后,在调试模式下,您会注意到即使提取产品,也会调用Reconnect()方法4-5次。获取产品后,为什么一次又一次地调用Reconnect()方法?
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()方法中做了很多事情。 此外,如果在获取产品后发生错误,则不要获取产品,只需调用Reconnect()方法,这就是其他原因。
Edit2 - 请不要仅仅通过查看代码来回复。如果您已经创建了一个表单并自己运行并且可以自己查看错误,那么请告知如何解决此问题。
更新 - 我知道我进入了无限次迭代。我试过这个,现在它起作用了:
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;
}
答案 0 :(得分:1)
这是因为如果没有网络连接,那么调用API网址无法连接,并且在catch
阻止您尝试重新连接
catch (Exception ex)
{
isDone = false;
ReconnectOnError(ex);
}
答案 1 :(得分:1)
你在这里有一个无意的循环:
如果FillProducts
失败,它会自行调用......
现在整个堆栈将在每次调用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;
}
要考虑的其他几点:
您不应该在GUI线程上进行网络I / O.您的GUI可能会无响应。考虑使用async / await(任务异步模式)
捕捉Exception
可能不是最好的主意。您应该捕捉到最具体的例外情况,并让其余部分由调用者处理。
答案 2 :(得分:0)
当没有互联网连接时.Count变量始终为零。