2012-06-12 3 views
0

this 게시물을 사용하여 예를 들어 200 개의 프록시를 확인하는 코드를 작성했습니다. 소켓의 시간 초과는 2 초입니다. 모든 것이 작동하지만, 코드 # 1은 2 초를 초과하는 200 개의 프록시를 확인하는 데 2 ​​분 이상 걸립니다. 그러나 코드 # 2으로 200 프록시를 확인하는 데 2 ​​초가 걸리고 코드 # 2으로 1000 프록시를 확인하는 데 2 ​​초가 걸립니다.왜 ThreadPool을 사용하여 프록시를 검사하는 것이 ThreadPool없이 동일한 작업을하는 것보다 시간이 오래 걸리나요?

코드 # 1은 ThreadPool을 사용합니다. 코드 # 1proxyCount 소켓을 열고 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

스레드 풀 시작 스레드가 그냥 아주 좋은 TP 스레드입니다. 그들은 실제 작업을 수행하지 않고 WaitOne() 호출을 차단합니다. 따라서 20 명이 즉시 실행을 시작하고 2 초 동안 완료되지 않습니다. 스레드 풀 스케줄러는 하나의 스레드가 완료되거나 다른 스레드가 이 아니거나이 0.5 초 이내에 완료 될 때만 스레드를 시작하도록 허용합니다. 그런 다음 추가로 실행할 수 있습니다. 따라서 모두 요청이 완료되기까지 시간이 걸립니다.

SetMinThreads()를 호출하고 최소값을 200으로 설정하면 문제를 해결할 수 있습니다.하지만 시스템 리소스가 엄청나게 낭비됩니다. Socket.BeginConnect()를 200 번 호출하고 2 초 후에 무슨 일이 있었는지 확인할 수도 있습니다. 당신의 빠른 버전.

+0

당신은 완전히 옳습니다. 그러나 ** 코드 # 1 **에는 2 분 이상이 소요됩니다. 20-30 초 - 좋아, 2 분. 왜 그런지 생각해 봤어? –

+0

적어도 1.5 분, 180 x 0.5 초입니다. 주전자는 끓일 때까지 더 오래 걸립니다. –

+0

같은 시간에 20 개의 스레드가 각각 2 초이므로 계산 결과 200 (프록시)/20 (스레드) * 2 (초) = 20 초 –

0

첫 번째 예와 비슷하게 각 프록시 연결이 시간 초과되거나 2 초 중 빠른 날짜가 오기를 기다리고 있습니다. 또한 200 개의 별도 작업 요청이 대기 중입니다. 스레드 풀 크기가 이보다 작을 수 있습니다. 그것을 GetMaxThreads으로 확인하십시오. 당신은 그 수의 작업 요청을 동시에 실행하게 될 것이고, 다음 요청은 이전 항목을 기다려야 타임 아웃 할 수 있습니다.

관련 문제