4
\$\begingroup\$

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);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.