2011-10-30 6 views
1

私は、サイトのhttp応答ステータスを返すスレッドを持っていますが、時には自分のプログラムからfalseの結果が返されます。しばらくすると良い結果が得られます。
Falseの結果は: は、それがチェックする時間の大きなマウントを取り、それが(例えば)Googleは非常に合理的ではないである、ダウンしていると言うが、数秒後にそれが良い結果C#false httpレスポンス

を返します。

あなたは見て、何が間違っていると教えてもらえますか?どのように改善することができますか?
をチェックデータグリッド内のすべてのサイト:

private void CheckSites() 
     { 
      if (CheckSelected()) 
      { 
       int rowCount = dataGrid.BindingContext[dataGrid.DataSource, dataGrid.DataMember].Count; 
       string url; 
       for (int i = 0; i < rowCount; i++) 
       { 
        url = dataGrid.Rows[i].Cells[2].Value.ToString(); 
        if (url != null) 
        { 
         Task<string[]> task = Task.Factory.StartNew<string[]> 
         (() => checkSite(url)); 

         // We can do other work here and it will execute in parallel: 
         //Loading... 

         // When we need the task's return value, we query its Result property: 
         // If it's still executing, the current thread will now block (wait) 
         // until the task finishes: 
         string[] result = task.Result; 
         selectRows(); 
         if (result[0] != System.Net.HttpStatusCode.OK.ToString() && result[0] != System.Net.HttpStatusCode.Found.ToString() && result[0] != System.Net.HttpStatusCode.MovedPermanently.ToString()) 
         { 
          //bad 
          notifyIcon1.ShowBalloonTip(5000, "Site Down", dataGrid.Rows[i].Cells[2].Value.ToString() + ", has a status code of:" + result, ToolTipIcon.Error); 
          dataGrid.Rows[i].DefaultCellStyle.BackColor = System.Drawing.Color.Wheat; 
          TimeSpan ts; 
          TimeSpan timeTaken = TimeSpan.Parse(result[1]); 
          dataGrid.Rows[i].Cells[3].Value = result[0]; 
          dataGrid.Rows[i].Cells[3].Style.BackColor = System.Drawing.Color.Red; 
          dataGrid.Rows[i].Cells[4].Value = timeTaken.Seconds.ToString() + "." + String.Format("{0:0.00000}", timeTaken.Milliseconds.ToString()) + " seconds."; 
          string sec = (DateTime.Now.Second < 10) ? "0" + DateTime.Now.Second.ToString() : DateTime.Now.Second.ToString(); 
          string min = (DateTime.Now.Minute < 10) ? "0" + DateTime.Now.Minute.ToString() : DateTime.Now.Minute.ToString(); 
          string hour = (DateTime.Now.Hour < 10) ? "0" + DateTime.Now.Hour.ToString() : DateTime.Now.Hour.ToString(); 
          dataGrid.Rows[i].Cells[5].Value = hour + ":" + min + ":" + sec; 

          //loadbar 
         } 
         else if (result[0] == "catch")//catch 
         { 
          notifyIcon1.ShowBalloonTip(10000, "SITE DOWN", dataGrid.Rows[i].Cells[1].Value.ToString() + ", Error:" +result[1], ToolTipIcon.Error); 
          dataGrid.Rows[i].Cells[3].Value = result[1]; 
          dataGrid.Rows[i].Cells[3].Style.BackColor = System.Drawing.Color.Red; 
          //loadbar 

         } 
         else 
         { 
          //good 
          TimeSpan timeTaken = TimeSpan.Parse(result[1]); 
          dataGrid.Rows[i].Cells[3].Value = result[0]; 
          dataGrid.Rows[i].Cells[3].Style.BackColor = System.Drawing.Color.LightGreen; 
          dataGrid.Rows[i].Cells[4].Value = timeTaken.Seconds.ToString() + "." + String.Format("{0:0.00000}", timeTaken.Milliseconds.ToString()) + " seconds."; 
          string sec = (DateTime.Now.Second < 10) ? "0" + DateTime.Now.Second.ToString() : DateTime.Now.Second.ToString(); 
          string min = (DateTime.Now.Minute < 10) ? "0" + DateTime.Now.Minute.ToString() : DateTime.Now.Minute.ToString(); 
          string hour = (DateTime.Now.Hour < 10) ? "0" + DateTime.Now.Hour.ToString() : DateTime.Now.Hour.ToString(); 
          dataGrid.Rows[i].Cells[5].Value = hour + ":" + min + ":" + sec; 
          //loadbar 
         } 
         selectRows(); 
        } 
       } 
      } 
     } 

をチェックサイト:事前に

///////////////////////////////// 
     ////Check datagrid websites-button - returns response 
     ///////////////////////////////// 
     private string[] checkSite(string url) 
     { 
      string[] response = new string[2]; 
      url = dataGrid.Rows[0].Cells[2].Value.ToString(); 
      if (url != null) 
      { 
       try 
       { 
        HttpWebRequest httpReq; 


        httpReq.Timeout = 10000; 
        //loadbar 
        dataGrid.Rows[0].DefaultCellStyle.BackColor = System.Drawing.Color.Wheat; 
        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); 
        timer.Start(); 
        HttpWebResponse httpRes = (HttpWebResponse)httpReq.GetResponse(); //httpRes.Close(); 
        timer.Stop(); 
        //loadbar 
        HttpStatusCode httpStatus = httpRes.StatusCode; 
        response[0] = httpStatus.ToString(); 
        response[1] = timer.Elapsed.ToString();//* 
        httpRes.Close(); 
        return response; 
       } 
       catch (Exception he) 
       { 
        response[0] = "catch"; 
        response[1] = he.Message; 
        return response; 
       } 
      } 
      response[0] = "catch"; 
      response[1] = "No URL entered"; 
      return response; 
      //dataGrid.Rows[i].DefaultCellStyle.BackColor = System.Drawing.Color.Blue; 

     } 

感謝。

+2

"偽の結果"と "良い結果"の意味を正確に説明してください。 – Oded

+0

いくつのサイトが並行してチェックインしていますか? – Yahia

+0

これはコンピュータ全体で起こっていますか?たとえば、Webブラウザを使用してGoogleにアクセスすると、もう一度失敗しますか? –

答えて

1

が使用される実際のコードです:すべての

まず、あなたの「偽の結果」の定義と「良い結果が」間違っています。 Aを期待してBを得ると、Bが無効であるとは限りません。あなたの妻が出産し、あなたが少年を期待しているが、それが女の子であることが判明した場合、それは偽の結果ではありません。ただ予期しない。

それは言った:あなたの仕事を分析することができます:場合は、最終的に取得するためにサイトをチェックするために長い時間がかかります???結果は200応答コードではありません。私たちは、あなたがタイムアウトを扱っているとほとんどうまく思うことができます。間にあなたのルータ、Googleまたは任意の基本的なネットワークデバイスが問題を抱えている場合、予期しない答えを得ることが期待されます。 "Timeout"、 "Bad Request"、 "Server not available"など。なぜこれが起こるのでしょうか?あなたの環境に直接アクセスすることなく確実に言うことは不可能です。

しかし、コードを見ると、各チェックをバックグラウンドでタスクとして実行するために、デフォルトのTaskSchedulerを使用していることがわかります(デフォルトのタスクスケジューラを変更しないと仮定すると、 )。デフォルトのタスクスケジューラは、スレッドプール上の各タスクをスケジューリングし、多くのタスクが同時に実行されるようにします。ここでは、ネットワークのオーバーロードに適した候補があります。多くのサイト(特にGoogle)は、同じソース(特に頻度が高い場合)からの多くのリクエストを処理するためにある種の機密性があるため、Googleがあなたを一時的にブロックしたり、返信したりしている可能性があります。繰り返しますが、この時点では純粋な推測ですが、スレッドプールが最大値にない限り、すべてのチェックを同時に実行しているという事実は、あなたの問題の原因である可能性が非常に高いです。

UPDATE

私はLimitedConcurrencyTaskScheduler(ここを参照してください:http://blogs.msdn.com/b/pfxteam/archive/2010/04/09/9990424.aspxを)での作業をお勧めします。ここでは、非同期に実行できるタスクの量を制限できます。あなたの状況で理想的には何の数のテストが必要ですか。また、頻度が「あまりにも高くない」ことを確認してください。高すぎるものを定義するのは難しいですが、テストだけでそのことを証明できます。

+0

はい私はGoogleが問題だと思っています。それを追加できたら、チェックしながらプログラムを解凍するために何をやりたいのですか? – funerr

+0

@ agam360 - 私は私の答えを更新しました。これはあなたを助けますか? – Polity

+0

最後に、私のコードが間違った応答時間を返すと思いますか? – funerr

0

シナリオをシミュレートするために、データグリッドとボタン付きのWinformを作成しました。フォームの読み込み時に、プログラムでURLのリストを(テーブル内に)作成し、データグリッドにバインドします。ボタンをクリックすると、ダウンロードプロセスが開始されます。簡潔に言えば、あなたはもっと守備的なコードと以下のコードを書いて、問題の修正方法の骨組みのみを書かなければならない。提供されているコードを仮定

using System; 
using System.Data; 
using System.Net; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace app 
{ 
    public partial class Form1 : Form 
    { 
     DataTable urls = new DataTable(); 
     public Form1() 
     { 
      InitializeComponent(); 
     } 
     //Fill your uri's and bind to a data grid. 
     void InitTable() 
     { 
      //Silly logic to simulate your scenario. 
      urls = new DataTable(); 
      urls.Columns.Add(new DataColumn("Srl", typeof(string))); 
      urls.Columns.Add(new DataColumn("Urls", typeof(Uri))); 
      urls.Columns.Add(new DataColumn("Result", typeof(string))); 

      DataRow dr = urls.NewRow(); 
      dr["Srl"] = "1"; 
      dr["Urls"] = new Uri("http://www.microsoft.com"); 
      dr["Result"] = string.Empty; 
      urls.Rows.Add(dr); 
      dr = urls.NewRow(); 
      dr["Srl"] = "2"; 
      dr["Urls"] = new Uri("http://www.google.com"); 
      dr["Result"] = string.Empty; 
      urls.Rows.Add(dr); 
      dr = urls.NewRow(); 
      dr["Srl"] = "3"; 
      dr["Urls"] = new Uri("http://www.stackoverflow.com"); 
      dr["Result"] = string.Empty; 
      urls.Rows.Add(dr); 
      urls.AcceptChanges(); 
     } 
     void UpdateResult() 
     { 
      dataGridView1.DataSource = urls; 
     } 

     //Important 
     // This example will freeze UI. You can avoid this while implementing 
     //background worker or pool with some event synchronization. I haven't covered those area since 
     //we are addressing different issue. Let me know if you would like to address UI freeze 
     //issue. Or can do it your self. 
     private void button1_Click(object sender, EventArgs e) 
     {    
      //Create array for Task to parallelize multiple download. 
      var tasks = new Task<string[]>[urls.Rows.Count]; 
      //Initialize those task based on number of Uri's 
      for(int i=0;i<urls.Rows.Count;i++) 
      { 
       int index = i;//Do not change this. This is to avoid data race 
       //Assign responsibility and start task. 
       tasks[index] = new Task<string[]>(
         () => checkSite(
          new TaskInput(urls.Rows[index]["Urls"].ToString(), urls.Rows[index]["Srl"].ToString()))); 
       tasks[index].Start(); 

      } 
      //Wait for all task to complete. Check other overloaded if interested. 
      Task.WaitAll(tasks); 

      //block shows how to access result from task 
      foreach (var item in tasks) 
      { 
       DataRow[] rows=urls.Select("Srl='"+item.Result[2]+"'"); 
       foreach (var row in rows) 
         row["Result"]=item.Result[0]+"|"+item.Result[1]; 
      } 
      UpdateResult(); 
     } 
     //This is dummy method which in your case 'Check Site'. You can have your own 
     string[] checkSite(TaskInput input) 
     { 
      string[] response = new string[3]; 
      if (input != null) 
      { 
       try 
       { 
        WebResponse wResponse = WebRequest.Create(input.Url).GetResponse(); 

        response[0] = wResponse.ContentLength.ToString(); 
        response[1] = wResponse.ContentType; 
        response[2] = input.Srl; 
        return response; 
       } 
       catch (Exception he) 
       { 
        response[0] = "catch"; 
        response[1] = he.Message; 
        response[2] = input.Srl; 
        return response; 
       } 
      } 
      response[0] = "catch"; 
      response[1] = "No URL entered"; 
      response[2] = input.Srl; 
      return response; 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      InitTable(); 
      UpdateResult(); 
     } 
    } 
    //Supply custom object for simplicity 
    public class TaskInput 
    { 
     public TaskInput(){} 
     public TaskInput(string url, string srl) 
     { 
      Url = url; 
      Srl = srl; 
     } 
     public string Srl { get; set; } 
     public string Url { get; set; } 
    } 
} 
+0

ありがとうございますが、私がやろうとしたことではありません(私はファイルをダウンロードしたくありません)。 – funerr

+0

@ agam360:ダウンロードはあなたのシナリオをシミュレートするだけで、問題の解決策ではありませんでした。あなたの問題に対する私の答えは、結果を取得する前に複数のタスクが完了するのを待つ方法が明白なbutton1_Clickイベントハンドラで見つけることができます。 –

関連する問題