2012-07-12 42 views
4

我正在开发一个应用程序,用于为Google + 1,Facebook共享和Tweets刮脸。我有一个请求方法接受一个URL,然后关闭并获取每个社交媒体类型的计数。请求方法和线程问题?

它的逻辑如下: -

  • 采取URL
  • 不要通过本地/默认的IP请求,直到我们得到速率限制/非500响应
  • 在错误
    • 呼叫SelectNewProxy()它遍历代理列表并返回一个随机尝试(避免IP请求限制的好方法)
    • 从列表中删除坏代理到av OID再次选择它
    • 开始其每递增第二
  • 当计时器== 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?

任何帮助非常感谢!

三江源

+0

您不详细说明计数器更新的位置;可能很难有人找出为什么柜台不再> = 600没有... – 2012-07-12 14:46:17

回答

1

你是如何宣称proxy?如果您正在多个线程上读取/写入其值,则应确保使用volatile关键字声明它,否则其他人不会在一个线程上写入proxy

例如为:

volatile WebProxy proxy; 
+0

只需在全球范围内公开声明。我实际上设法通过在重置计数器之前等待一段时间来排序(允许其他线程赶上),但这显然是一个糟糕的解决方案,所以我肯定会给出这一点去感谢! – dtsg 2012-07-13 07:36:13

+0

这里有很多关于'volatile'的实用信息:http://www.bluebytesoftware.com/blog/2008/06/13/VolatileReadsAndWritesAndTimeliness.aspx。 – 2012-07-13 16:01:28

0

看起来像你对我有一个范围的问题。如果我正确地解释了您的帖子,则会为您发布的请求方法的每次调用创建一个线程。

该方法中声明的任何东西显然都是您的新线程的一部分。该方法之外的任何内容都可能不属于新线程的一部分。这意味着你最终可能会有多个线程试图做一些事情来声明线程之间共享的内容。在这种情况下,您可以从多个线程访问代理。因为这是一个对象的实例,所以在设置代理变量之前应该将其锁定。 我们锁定(代理){//使用代理的代码}为线程安全地设置该变量。