Windows 服务命中 API 多次有时
Windows service Hit API Multiple Time Sometimes
我正在使用 windows 服务进行呼叫 API,在 Sql 中获得响应和更新 Table 它工作正常,但有时会命中 API 两次。我找不到理由。这是我的代码
protected override void OnStart(string[] args)
{
this.timer = new System.Timers.Timer(15000D);
this.timer.AutoReset = true;
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
this.timer.Start();
}
protected override void OnStop()
{
this.timer.Stop();
this.timer = null;
}
protected void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.proccessQue();
}
这是 proccessQue() 方法
//SELECT record form table
SqlDataAdapter adap = new SqlDataAdapter("SELECT * FROM TABLE_NAME WHERE is_done=0 AND date>DATEADD(minute,-5,GETDATE())", conn);
DataTable dt = new DataTable();
adap.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
string parameters= dt.Rows[i]["parameters"] + "";
string api = "http://domain.com/page.aspx?parameters=" + parameters;
HttpWebRequest httpreq = (HttpWebRequest)WebRequest.Create(api);
HttpWebResponse httpres = (HttpWebResponse)httpreq.GetResponse();
StreamReader sr = new StreamReader(httpres.GetResponseStream());
string results = sr.ReadToEnd();
sr.Close();
if (results.Contains("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"))
{
try
{
string response= "";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(results);
var res2 = xmlDoc.SelectNodes("RechargeRequest/RequestResponse/APIRef");
if (res2 != null)
response= res2[0].InnerText;
SqlCommand cmd = new SqlCommand("UPDATE TABLE_NAME SET field='" + response+ "',is_done=1 WHERE id=" + rId, conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
}
}
}
请帮我看看哪里错了。
根据我对原始问题的评论,有几点需要注意。
- API 将根据查询结果被命中 0-n 次。现在定时器将在每个时间间隔异步执行
timer_Elapsed()
方法。因此,如果 processQue()
方法花费的时间超过 15 秒,则可能会为每个项目多次调用 API。
因此,一种选择是 Stop
计时器执行您的流程逻辑,Start()
计时器在 processQue()
方法完成时执行。如:
protected void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.timer.Stop(); //stop the timer
this.proccessQue(); //process the queue
this.timer.Start(); //restart the timer
}
这样可以确保 processQue();
在再次调用 timer_Elapsed()
事件之前完成。
现在,如果 processQue()
方法出现异常,将不会继续执行。如何处理这取决于你,但一个简单的 try .. catch
将处理异常(不正确但会)。
现在我对代码的第二个担心,这与执行多次运行的原因无关,是 类 的使用和未正确处理。
首先.. Why use a SqlDataAdapter
when a SqlDataReader
will produce a faster execution. 这是基于意见的,但是不需要 DataTable
并且会将整个结果读入内存。 ho 看起来你只使用了 Sql 查询的两列(不确定 rId
来自哪里),所以不要使用 *
,而是定义你实际需要的列名。这将减少从 Sql 查询中查询和流式传输的数据量。在小型查询中可能看起来微不足道,但在更大的查询和更大的数据集中会产生很大的不同。
我看到的下一期是 IDisposable
的使用而不处理它们。
SqlDataAdapter
StreamReader
SqlCommand
这些都是类继承自IDisposable
so should be wrapped in a using
statement or disposed of manually calling the Dispose()
方法
我正在使用 windows 服务进行呼叫 API,在 Sql 中获得响应和更新 Table 它工作正常,但有时会命中 API 两次。我找不到理由。这是我的代码
protected override void OnStart(string[] args)
{
this.timer = new System.Timers.Timer(15000D);
this.timer.AutoReset = true;
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
this.timer.Start();
}
protected override void OnStop()
{
this.timer.Stop();
this.timer = null;
}
protected void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.proccessQue();
}
这是 proccessQue() 方法
//SELECT record form table
SqlDataAdapter adap = new SqlDataAdapter("SELECT * FROM TABLE_NAME WHERE is_done=0 AND date>DATEADD(minute,-5,GETDATE())", conn);
DataTable dt = new DataTable();
adap.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
string parameters= dt.Rows[i]["parameters"] + "";
string api = "http://domain.com/page.aspx?parameters=" + parameters;
HttpWebRequest httpreq = (HttpWebRequest)WebRequest.Create(api);
HttpWebResponse httpres = (HttpWebResponse)httpreq.GetResponse();
StreamReader sr = new StreamReader(httpres.GetResponseStream());
string results = sr.ReadToEnd();
sr.Close();
if (results.Contains("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"))
{
try
{
string response= "";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(results);
var res2 = xmlDoc.SelectNodes("RechargeRequest/RequestResponse/APIRef");
if (res2 != null)
response= res2[0].InnerText;
SqlCommand cmd = new SqlCommand("UPDATE TABLE_NAME SET field='" + response+ "',is_done=1 WHERE id=" + rId, conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
}
}
}
请帮我看看哪里错了。
根据我对原始问题的评论,有几点需要注意。
- API 将根据查询结果被命中 0-n 次。现在定时器将在每个时间间隔异步执行
timer_Elapsed()
方法。因此,如果processQue()
方法花费的时间超过 15 秒,则可能会为每个项目多次调用 API。
因此,一种选择是 Stop
计时器执行您的流程逻辑,Start()
计时器在 processQue()
方法完成时执行。如:
protected void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.timer.Stop(); //stop the timer
this.proccessQue(); //process the queue
this.timer.Start(); //restart the timer
}
这样可以确保 processQue();
在再次调用 timer_Elapsed()
事件之前完成。
现在,如果 processQue()
方法出现异常,将不会继续执行。如何处理这取决于你,但一个简单的 try .. catch
将处理异常(不正确但会)。
现在我对代码的第二个担心,这与执行多次运行的原因无关,是 类 的使用和未正确处理。
首先.. Why use a SqlDataAdapter
when a SqlDataReader
will produce a faster execution. 这是基于意见的,但是不需要 DataTable
并且会将整个结果读入内存。 ho 看起来你只使用了 Sql 查询的两列(不确定 rId
来自哪里),所以不要使用 *
,而是定义你实际需要的列名。这将减少从 Sql 查询中查询和流式传输的数据量。在小型查询中可能看起来微不足道,但在更大的查询和更大的数据集中会产生很大的不同。
我看到的下一期是 IDisposable
的使用而不处理它们。
SqlDataAdapter
StreamReader
SqlCommand
这些都是类继承自IDisposable
so should be wrapped in a using
statement or disposed of manually calling the Dispose()
方法