使用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); }
}
答案 0 :(得分:1)
你启动的线程池线程只是不是很好的tp线程。它们不执行任何实际工作,只是阻止WaitOne()调用。因此,其中20个立即开始执行,并且没有完成2秒。线程池调度程序仅允许另一个线程在其中一个线程完成时启动,或者 none 在0.5秒内完成。然后允许额外的一个运行。因此,在所有请求完成之前需要一段时间。
您可以通过调用SetMinThreads()并将最小值设置为200来修复它。但这极其浪费系统资源。您也可以将Socket.BeginConnect()调用200次,然后查看2秒后发生的事情。你的快速版本。
答案 1 :(得分:0)
在第一个示例中,您正在等待每个代理连接超时,或者等待2秒,以先到者为准。此外,您正在排队200个单独的工作请求。你的线程池大小可能会比这个小。请使用GetMaxThreads进行检查。您只会同时运行该数量的工作请求,并且下一个请求必须等待上一个项目超时。