2017-02-28 3 views
1

私はコールAPIにWindowsサービスを使用しています.Sqlテーブルで応答と更新を取得しています。うまくいきましたが、しばらくヒットAPIが2回あります。私は後ろに理由がありません。私が間違ってつもりであるのはここ、ここproccessQueされる私のコードWindowsサービスヒット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(); 
} 

されており、()メソッド

//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) 
    { 

    } 
    } 
} 

は私を助けてください。

+0

複数のもの1. API呼び出しがレコードのループ内にあります。あなたのループの結果に基づいて、0-n回ヒットします。クエリが複数のメソッドを返す可能性があります。 2. processQueueメソッドがタイマーの各経過イベントよりも時間がかかる可能性はありますか?私の提案は1になるだろう。2つ以上のレコードを返す可能性があるので、クエリの結果を確認します。2.経過イベントでタイマーを停止してキューを処理し、再起動します。最後に、これは2017ですが、非同期/待機パターンを使用し、Web要求に対してより堅牢なHttpClientクラスを使用する方がよいでしょう。 – Nico

+0

ああ、最後にあなたはかなりの数のIDisposableが処分されていない – Nico

+0

はい可能です。クエリは1つ以上の行を返します。経過イベントでタイマーを停止する方法は、キューを処理し、それを再起動しますか?私を助けてください。私は充電時間のためにタイマーの経過時間を増やすことができないので、充電のウェブサイトのためにこのサービスを使用しています。 –

答えて

1

元の質問に対する私のコメントに基づいて、いくつか見ていくべきことがあります。

  1. APIは、クエリの結果に基づいて0〜n回ヒットします。これで、タイマーは、間隔ごとに非同期的にtimer_Elapsed()メソッドを実行します。したがって、processQue()メソッドが15秒以上かかる場合、APIは各アイテムに対して複数回呼び出されることがあります。

したがって一つの選択肢は、あなたのプロセスロジックとStart()processQue()メソッドが終了するタイマーを実行するタイマーをStopすることです。以下のような:

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 
} 

だから、これはtimer_Elapsed()イベントが再び呼び出されるprocessQue();終了する前に保証します。

processQue()メソッドで例外が発生した場合、実行は続行されません。これを処理する方法はあなた次第ですが、単純なtry .. catchは例外を処理します(正しくはできませんが)。

私の2番目の懸念はコードにありますが、これは何回も実行が実行される理由とは関係なく、クラスの使用であり、正しく処理されません。

最初に.. Why use a SqlDataAdapter when a SqlDataReader will produce a faster execution.これは意見に基づいていますが、DataTableを必要とせず、結果全体をメモリに読み込みます。 hoそれは*を使用するのではなく、実際に必要な列名を定義するために、2つの列(rIdがどこから来るかわからない)を使用しているようです。これにより、SQLクエリからクエリおよびストリーミングされるデータの量が削減されます。小さなクエリでは些細なことに思えるかもしれませんが、大きなクエリや大きなデータセットでは大きな違いがあります。

次の問題は、IDisposableを使用して処分しないことです。

  1. SqlDataAdapter
  2. StreamReader
  3. SqlCommand

これらはとてもusing声明に包まれた、または手動Dispose()メソッドを呼び出すに処分しなければならないIDisposableから継承するすべてのクラスです。

+0

@Nicoありがとうございます! –