为什么使用ThreadPool检查代理比没有ThreadPool时使用ThreadPool需要花费更多的时间?

时间:2012-06-12 14:08:37

标签: c# multithreading threadpool asyncsocket socks

使用this帖子我编写的代码可以检查200个代理。套接字超时为2秒。一切正常,但代码#1 的问题需要超过2分钟来检查200个代理,限制为2秒超时。但是使用代码#2 ,需要2秒才能检查200个代理,并且还需要2秒来检查1000个代理代码#2

代码#1 使用ThreadPool。 代码#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); }
}

2 个答案:

答案 0 :(得分:1)

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

您可以通过调用SetMinThreads()并将最小值设置为200来修复它。但这极其浪费系统资源。您也可以将Socket.BeginConnect()调用200次,然后查看2秒后发生的事情。你的快速版本。

答案 1 :(得分:0)

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