4

Google+1、Facebook の共有、ツイート用に Web サイトをスクレイピングするアプリを開発しています。URL を受け取り、ソーシャル メディアの種類ごとにカウントを取得するリクエスト メソッドがあります。

そのロジックは次のとおりです。

  • URLを取る
  • レート制限された/500 以外の応答が得られるまで、ローカル/デフォルト IP を介して要求を行います
  • エラー時
    • SelectNewProxy()プロキシのリストを繰り返し処理し、ランダムに 1 つを返す呼び出し(IP のリクエスト制限を回避する良い方法)
    • リストから不適切なプロキシを削除して、再度選択しないようにします
    • 毎秒インクリメントするタイマーを開始する
  • タイマー == 600 (10 分) の場合
    • 新規作成WebProxyし、ローカル/デフォルト IP の背後にあるリクエストを再度試行します
    • タイマーをリセット

すすいで繰り返す

コードは次のとおりです。

public string Request(string action)
{
      HttpWebRequest req;

      OnStatusChange(new MyArgs() { Message = "Status: Requesting..." });
      string response = string.Empty;

      while (response.Equals(string.Empty) && proxy != null)
      {
             try
             {
                  req = (HttpWebRequest)WebRequest.Create(action);
                  req.Proxy = proxy;
                  HandleUIMessages(action, proxy);
                  response = new StreamReader(req.GetResponse().GetResponseStream()).ReadToEnd();
              }
              catch
              {
                  //OnProxyChange(new MyArgs() { ProxyMessage = string.Format("Proxy: {0}", proxy.Address.ToString()) });
                  RemoveProxy(proxy);

                  if (!timer.Enabled)
                  {
                      timer.Interval = (int)TimeInterval.OneSecond;
                      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
                      timer.Enabled = true;
                      timer.Start();
                  }
                  WebProxy reset = new SelectNewProxy();     
                  proxy = counter >= 600 ? reset : proxy = SelectNewProxy();
               }
      }
      return response;
}

私が使用していてThreadPool、各リクエストが独自のスレッドで実行されていることに言及する価値があります。機能するようですが、目的の効果が得られません。カウンターは「600」に達して設定されますproxy = resetが、それは非常に短時間しか行わないように見えます。おそらく最初にヒットしたスレッドのみですか? その後、timer_Elapsedが呼び出されcounterてリセットされます。スレッドがヒットし、割り当てproxy = resetてから、リセットされたためcounter(>= 600 ではなくなった)、後続のキューに入れられたすべてのスレッドが を呼び出す可能性がありSelectNewProxy()ますか? とりとめのないように感じますが、誰かが私が言おうとしていることを理解してくれることを願っています。私の推測が正しければ、すべてのスレッドがproxy = reset最初の IP を取得して再試行できるようにするにはどうすればよいですか?

どんな助けでも大歓迎です!

ありがとうございました

4

2 に答える 2

1

どのように宣言しましたproxyか?複数のスレッドでその値を読み書きする場合は、必ずvolatileキーワードを使用して宣言する必要があります。そうしないとproxy、1 つのスレッドへの書き込みが他のスレッドで観察されない可能性があります。

例えば:

volatile WebProxy proxy;
于 2012-07-12T22:37:57.847 に答える
0

スコーピングに問題があるように見えます。私があなたの投稿を正しく解釈した場合、投稿した Request メソッドへの呼び出しごとにスレッドを作成します。

メソッドで宣言されたものはすべて、明らかに新しいスレッドの一部です。メソッドの外にあるものは、新しいスレッドの一部ではない可能性があります。これは、複数のスレッドがスレッド間で共有されている状態に何かをしようとすることになる可能性があることを意味します。この場合、複数のスレッドからプロキシにアクセスします。これはオブジェクトのインスタンスであるため、プロキシ変数を設定する前にロックする必要があります。lock (proxy) { // プロキシを使用するコード } を使用して、その変数にスレッドセーフな設定を行います。

于 2012-07-18T13:58:09.220 に答える