0

例如,使用这篇文章,我编写了检查 200 个代理的代码。套接字的超时时间为 2 秒。一切正常,但问题是代码 #1需要超过 2 分钟才能检查 200 个代理,限制为 2 秒超时。但是使用Code #2检查 200 个代理需要 2 秒,使用Code #2检查 1000 个代理也需要 2 秒。

代码 #1使用线程池。 代码 #1打开proxyCount套接字,进入休眠状态 2 秒,然后检查成功。正好需要 2 秒。

那么代码 #1中的问题在哪里?为什么至少有 20 个线程的 ThreadPool 比没有线程的要慢得多?

代码 #1

int proxyCount = 200;  
CountdownEvent cde = new CountdownEvent(proxyCount);     
private void RefreshProxyIPs(object obj)
{     
    int workerThreads, ioThreads;
    ThreadPool.GetMinThreads(out workerThreads, out ioThreads);
    ThreadPool.SetMinThreads(20, ioThreads);

    var proxies = GetServersIPs(proxyCount);
    watch.Start();
    for (int i = 0; i < proxyCount; i++)
    {
        var proxy = proxies[i];
        ThreadPool.QueueUserWorkItem(CheckProxy, new IPEndPoint(IPAddress.Parse(proxy.IpAddress), proxy.Port));
    }
    cde.Wait();
    cde.Dispose();
    watch.Stop();
}

private List<IPEndPoint> list = new List<IPEndPoint>();
private void CheckProxy(object o)
{
     var proxy = o as IPEndPoint;
     using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
     {
         var asyncResult = socket.BeginConnect(proxy.Address, proxy.Port, null, null);
         if (asyncResult.AsyncWaitHandle.WaitOne(2000))
         {
             try
             {
                 socket.EndConnect(asyncResult);
             }
             catch (SocketException)
             {
             }
             catch (ObjectDisposedException)
             {
             }
         }
         if (socket.Connected)
         {
             list.Add(proxy);
             socket.Close();
         }
     }
     cde.Signal();
}

代码 #2

int proxyCount = 200;
var sockets = new Socket[proxyCount];
var socketsResults = new IAsyncResult[proxyCount];
var proxies = GetServersIPs(proxyCount);
for (int i = 0; i < proxyCount; i++)
{
      var proxy = proxies[i];
      sockets[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      socketsResults[i] = sockets[i].BeginConnect(IPAddress.Parse(proxy.IpAddress), proxy.Port, null, proxy);             
}
Thread.Sleep(2000);
for (int i = 0; i < proxyCount; i++)
{
     var success = false;
     try
     {
         if (socketsResults[i].IsCompleted)
         {
              sockets[i].EndConnect(socketsResults[i]);
              success = sockets[i].Connected;
              sockets[i].Close();
         }

         sockets[i].Dispose();
     }
     catch { }

     var proxy = socketsResults[i].AsyncState as Proxy;
     if (success) {  _validProxies.Add(proxy); }
}
4

2 回答 2

1

您启动的线程池线程不是很好的 tp 线程。他们不执行任何实际工作,只是阻止 WaitOne() 调用。所以其中 20 个立即开始执行,并且在 2 秒内没有完成。线程池调度程序只允许另一个线程在其中一个完成或在 0.5 秒内没有完成时启动。然后它允许额外的一个运行。所以需要一段时间才能完成所有请求。

您可以通过调用 SetMinThreads() 并将最小值设置为 200 来修复它。但这非常浪费系统资源。您不妨调用 Socket.BeginConnect() 200 次,然后在 2 秒后找出发生了什么。您的快速版本。

于 2012-06-12T14:22:23.450 回答
0

看起来在第一个示例中,您正在等待每个代理连接超时或 2 秒,以先到者为准。另外,您正在排队 200 个单独的工作请求。您的线程池大小可能会比这小得多。使用GetMaxThreads检查它。您只会同时运行该数量的工作请求,并且下一个请求必须等待前一个项目超时。

于 2012-06-12T14:24:31.147 回答