4

我正在开发一个应用程序,它可以为 Google+1、Facebook 分享和推文抓取网站。我有一个接受 URL 的请求方法,然后关闭并获取每种社交媒体类型的计数。

其逻辑如下:-

  • 取网址
  • 通过本地/默认 IP 进行请求,直到我们获得速率受限/非 500 响应
  • 出错时
    • 调用SelectNewProxy()迭代代理列表并随机返回一个尝试(避免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可能不会被其他线程观察到。

例如:

volatile WebProxy proxy;
于 2012-07-12T22:37:57.847 回答
0

在我看来,您的范围界定问题。如果我正确解释了您的帖子,您将为您发布的请求方法的每个调用创建一个线程。

Anything declared in the method obviously is part of your new thread. Anything outside the method is likely to not be part of your new thread. This means you may end up with multiple threads trying to do stuff to state that is shared between threads. In this case you access proxy from multiple threads. As this is an instance of an object you should lock it before setting the proxy variable. Us lock (proxy) { // code using proxy } to do a thread safe set to that variable.

于 2012-07-18T13:58:09.220 回答