C # Async WebRequests: странные результаты - PullRequest
0 голосов
/ 01 июня 2011

У меня есть небольшая консольная программа на C #, предназначенная для запуска списка URL-адресов и получения html с соответствующей страницы.В некоторой степени это работает, но у меня проблемы с тем, чтобы Async callbacks выполнялось надлежащее количество раз и обрабатывал таймауты.

Проблема: Я получаю точечные результаты.Иногда я запускаю код и результаты соответствуют ожидаемым (например, я даю ему 7 URL-адресов для просмотра, и он выводит 7 результатов и 1 завершенное событие), но в других случаях результаты не имеют смысла для меня (например, я запускаю7 URL-адресов и получите 2 или 3 полных события или только 6 результатов без полного события вообще).Может ли кто-нибудь объяснить, почему это происходит и как это исправить?

Результаты могут отличаться даже при использовании одинаковых 7 URL-адресов.Я предполагаю, что это потому, что иногда тайм-ауты сайта истекают, но мой код предназначен для корректной обработки тайм-аутов.Он также предназначен для обработки неправильных URL-адресов.Дайте ему несколько прогонов и дайте мне знать, что вы думаете.

Это сводит меня с ума!

Важно, чтобы окончательное решение обрабатывало неправильные URL-адреса, тайм-ауты и сайты, которыене существуетСобытие onComplete должно инициироваться после обработки всех URL-адресов.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace AsyncApp_03
{
    using System;
    using System.Net;
    using System.IO;
    using System.Text;
    using System.Threading;


    class Program
    {
        static int _count = 0;
        static int _invalid = 0;
        static int _total = 0;

        static void Main(string[] args)
        {
            ArrayList alSites = new ArrayList();
            alSites.Add("http://www.google.com");
            alSites.Add("adsfsdfsdfsdffd");
            alSites.Add("http://wwww.fjasjfejlajfl");
            alSites.Add("http://mundocinema.com/noticias/the-a-team-2/4237");
            alSites.Add("http://www.spmb.or.id/?p=64");
            alSites.Add("http://gprs-edge.ru/?p=3");
            alSites.Add("http://blog.tmu.edu.tw/MT/mt-comments.pl?entry_id=3141");

            _total = alSites.Count;
            ScanSites(alSites);

            Console.Read();
        }

        private static void ScanSites(ArrayList sites)
        {
            foreach (string uriString in sites)
            {
                try
                {
                    WebRequest request = HttpWebRequest.Create(uriString);
                    request.Method = "GET";
                    object data = new object(); //container for our "Stuff"

                    // RequestState is a custom class to pass info to the callback
                    RequestState state = new RequestState(request, data, uriString);
                    IAsyncResult result = request.BeginGetResponse(new AsyncCallback(UpdateItem), state);


                    //Register the timeout callback
                    ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(ScanTimeoutCallback), state, (5 * 1000), true);
                }
                catch
                {
                    Console.WriteLine("Invalid URL: " + uriString);
                    _invalid++;
                    Console.WriteLine("Count: " + (_invalid + _count));
                    Console.WriteLine("----------------------------------------------");
                }

            }
        }


        private static void UpdateItem(IAsyncResult result)
        {
            try
            {
                // grab the custom state object
                RequestState state = (RequestState)result.AsyncState;
                WebRequest request = (WebRequest)state.Request;

                // get the Response
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
                Stream s = (Stream)response.GetResponseStream();
                StreamReader readStream = new StreamReader(s);

                // dataString will hold the entire contents of the requested page if we need it.
                string dataString = readStream.ReadToEnd();
                response.Close();
                s.Close();
                readStream.Close();

                //Console.WriteLine(dataString);
                Console.WriteLine("Site HTML: " + state.SiteUrl);
            }
            catch
            {
                RequestState state = (RequestState)result.AsyncState;
                WebRequest request = (WebRequest)state.Request;
                Console.WriteLine("Couldn't Resolve URL: " + state.SiteUrl);
            }

            Interlocked.Increment(ref _count);
            Console.WriteLine("Count: " + (_invalid + _count));
            Console.WriteLine("----------------------------------------------");

            // All URL look-ups complete
            if ((_count + _invalid) == _total)
            {
                Console.WriteLine("Complete!");
            }
        }


        private static void ScanTimeoutCallback(object state, bool timedOut)
        {
            if (timedOut)
            {
                RequestState reqState = (RequestState)state;
                if (reqState != null)
                {
                    reqState.Request.Abort();
                }
                Console.WriteLine("aborted- timeout");
            }
        }


        class RequestState
        {
            public WebRequest Request; // holds the request
            public object Data; // store any data in this
            public string SiteUrl; // holds the UrlString to match up results (Database lookup, etc).

            public RequestState(WebRequest request, object data, string siteUrl)
            {
                this.Request = request;
                this.Data = data;
                this.SiteUrl = siteUrl;
            }

        }
    }
}
...