I am validating a collection of proxy servers and trying to achieve the maximum possible throughput. I've tested a few different methods, such as Task.WhenAll
, TPL Dataflow, and HttpWebRequest.BeginGetResponse
. From my testing I've found BeginGetResponse
to be the best for my use case. However, I have 2 different implementations that I would like to request a comparative review for, both of which work well (I can test >2k proxies in about 10 seconds, which is my timeout for the requests), but perhaps one of the implementations has advantages over the other:
Implementation A
private async void validateProxies(ICollection<Proxy> proxies)
{
await BeginTest(proxies, judges, 10000);
MessageBox.Show("Done!");
}
public static async Task BeginTest(ICollection<Proxy> proxies, ICollection<ProxyJudge> judges, int timeout = 10000)
{
await Task.Run(() =>
{
var mre = new ManualResetEvent(false);
var count = 0;
foreach (var proxy in proxies)
{
proxy.Status = ProxyStatus.Testing;
proxy.BeginTest(judges.GetRandomItem(), new Action<ProxyStatus>(status =>
{
proxy.Status = status;
Interlocked.Increment(ref count);
if (count == proxies.Count)
{
mre.Set();
}
}), timeout);
}
mre.WaitOne();
});
}
Implementation B
private void validateProxies(ICollection<Proxy> proxies)
{
BeginTest(proxies, judges, 10000, () =>
{
MessageBox.Show("Done!");
});
}
public static void BeginTest(ICollection<Proxy> proxies, ICollection<ProxyJudge> judges, int timeout = 10000, Action callback = null)
{
var count = 0;
foreach (var proxy in proxies)
{
proxy.Status = ProxyStatus.Testing;
proxy.BeginTest(judges.GetRandomItem(), new Action<ProxyStatus>(status =>
{
proxy.Status = status;
Interlocked.Increment(ref count);
if (count == proxies.Count)
{
if (callback != null)
{
callback();
}
}
}), timeout);
}
}
proxy.BeginTest
public void BeginTest(IProxyTest test, Action<ProxyStatus> callback, int timeout = 10000)
{
var req = HttpWebRequest.Create(test.URL);
req.Proxy = new WebProxy(this.ToString());
req.Timeout = timeout;
WebHelper.BeginGetResponse(req, new Action<RequestCallbackState>(callbackState =>
{
if (callbackState.Exception != null)
{
callback(ProxyStatus.Invalid);
}
else
{
var responseStream = callbackState.ResponseStream;
using (var reader = new StreamReader(responseStream))
{
var responseString = reader.ReadToEnd();
if (responseString.Contains(test.Validation))
{
callback(ProxyStatus.Valid);
}
else
{
callback(ProxyStatus.Invalid);
}
}
}
}));
}
WebHelper.BeginGetResponse
public static void BeginGetResponse(WebRequest request, Action<RequestCallbackState> responseCallback)
{
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, request.Timeout, true);
asyncTask.ContinueWith(task =>
{
WebResponse response = task.Result;
Stream responseStream = response.GetResponseStream();
responseCallback(new RequestCallbackState(responseStream));
responseStream.Close();
response.Close();
}, TaskContinuationOptions.NotOnFaulted);
//Handle errors
asyncTask.ContinueWith(task =>
{
var exception = task.Exception;
responseCallback(new RequestCallbackState(exception.InnerException));
}, TaskContinuationOptions.OnlyOnFaulted);
}