2012-06-12 1 views
0

Использование this сообщение Я написал код, который проверяет 200 прокси, например. Таймаут для сокета - 2 сек. Все работает, но проблема в том, что Код №1 занимает более 2 минут, чтобы проверить 200 прокси, ограниченных таймаутом в 2 сек. Но с Код №2 требуется 200 секунд, чтобы проверить 200 прокси, и потребовалось бы 2 секунды, чтобы проверить 1000 прокси с Код №2.Почему проверка прокси с помощью ThreadPool занимает гораздо больше времени, чем при использовании ThreadPool?

Код №1 использует ThreadPool. Код №1 открывает proxyCount розетки, переходит в режим сна за 2 секунды и проверяет, что сработало. Он занимает ровно 2 секунды.

Итак, где проблема в Код №1? Почему ThreadPool с минимальными 20 потоками намного медленнее, чем без него?

код # 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); } 
} 

ответ

1

ThreadPool темы вы начинаете просто не очень хорошие Т.П. нити. Они не выполняют никакой реальной работы, а просто блокируют вызов WaitOne(). Таким образом, 20 из них сразу начинают работать и не работают в течение 2 секунд. планировщик потокаpool разрешает запуск другого потока только тогда, когда один из них завершается, или нет из них завершены в течение 0,5 секунд. Затем он позволяет запускать дополнительный. Так что требуется до все Запросы завершены.

Вы можете исправить это, вызвав SetMinThreads() и установив минимум на 200. Но это невероятно расточительно для системных ресурсов. Вы могли бы также вызвать Socket.BeginConnect() 200 раз и узнать, что произошло через 2 секунды. Ваша быстрая версия.

+0

Вы совершенно правы, но это страх, что для ** кода № 1 ** требуется более 2 минут. 20-30 секунд - нормально, но 2 минуты. У вас есть идеи, почему это так? –

+0

Это не менее 1,5 минут, 180 х 0,5 секунды. Наблюдаемый чайник занимает больше времени, чтобы кипеть. –

+0

20 потоков в то же время, по 2 секунды, поэтому мои вычисления дают мне 200 прокси/20 (потоки) * 2 (секунды) = 20 секунд –

0

Похоже, что в первом примере вы ожидаете, что каждое прокси-соединение перейдет в таймаут, или 2 секунды, в зависимости от того, что наступит раньше. Кроме того, вы запускаете 200 отдельных рабочих запросов. Размер вашего пула потоков, вероятно, будет меньше этого. Проверьте его с помощью GetMaxThreads. У вас будет только такое количество рабочих запросов, выполняемых одновременно, и следующий запрос должен ждать предыдущего элемента до таймаута.

 Смежные вопросы

  • Нет связанных вопросов^_^