Вопрос

У меня есть страница, на которой необходимо объединить данные из четырех разных веб-запросов в один список элементов. В настоящее время я запускаю их последовательно, добавляю в один список, а затем связываю этот список с моим повторителем.

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

Как я могу выполнить четыре (это может даже увеличиться!) одновременно, помня о том, что каждый результат должен быть введен в один список?

большое спасибо!

РЕДАКТИРОВАТЬ: упрощенный пример того, что я делаю:

var itm1 = Serialize(GetItems(url1));
list.AddRange(itm1);
var itm2 = Serialize(GetItems(url2));
list.AddRange(itm2); 

string GetItems(string url)
{
     var webRequest = WebRequest.Create(url) as HttpWebRequest;
     var response = webRequest.GetResponse() as HttpWebResponse;

     string retval;
     using (var sr = new StreamReader(response.GetResponseStream()))
     { retval = sr.ReadToEnd(); }
     return retval;
} 
Это было полезно?

Решение

Это должно быть действительно просто, поскольку ваши окончательные данные зависят от результата всех четырех запросов.

Вы можете создать 4 асинхронных делегата, каждый из которых указывает на соответствующий веб-метод. Сделайте BeginInvoke на всех из них. А затем используйте WaitHandle, чтобы ждать всех. В вашем случае нет необходимости использовать обратные вызовы, так как вы не хотите продолжать работу во время обработки веб-методов, а скорее ждете, пока все веб-методы завершат выполнение.

Только после того, как все веб-методы будут выполнены, код после оператора wait будет выполнен. Здесь вы можете объединить 4 результата.

Вот пример кода, который я разработал для вас:

class Program
    {
        delegate string DelegateCallWebMethod(string arg1, string arg2);

        static void Main(string[] args)
        {
            // Create a delegate list to point to the 4 web methods
            // If the web methods have different signatures you can put them in a common method and call web methods from within
            // If that is not possible you can have an List of DelegateCallWebMethod
            DelegateCallWebMethod del = new DelegateCallWebMethod(CallWebMethod);

            // Create list of IAsyncResults and WaitHandles
            List<IAsyncResult> results = new List<IAsyncResult>();
            List<WaitHandle> waitHandles = new List<WaitHandle>();

            // Call the web methods asynchronously and store the results and waithandles for future use
            for (int counter = 0; counter < 4; )
            {
                IAsyncResult result = del.BeginInvoke("Method ", (++counter).ToString(), null, null);
                results.Add(result);
                waitHandles.Add(result.AsyncWaitHandle);
            }

            // Make sure that further processing is halted until all the web methods are executed
            WaitHandle.WaitAll(waitHandles.ToArray());

            // Get the web response
            string webResponse = String.Empty;
            foreach (IAsyncResult result in results)
            {
                DelegateCallWebMethod invokedDel = (result as AsyncResult).AsyncDelegate as DelegateCallWebMethod;
                webResponse += invokedDel.EndInvoke(result);
            }
        }


        // Web method or a class method that sends web requests
        public static string CallWebMethod(string arg1, string arg2)
        {
            // Code that calls the web method and returns the result

            return arg1 + " " + arg2 + " called\n";
        }

    }

Другие советы

Как насчет запуска каждого запроса в отдельном потоке, а затем добавления результатов в список?

вы можете проверить этот следующий код:

Parallel.Invoke (() = >                         {
                            // TODO запускает ваши запросы ...                         });

Вам нужны ссылки на параллельные расширения: http://msdn.microsoft.com/en-us/concurrency/bb896007. ASPX

@Josh: Что касается вашего вопроса об отправке 4 (возможно, более) асинхронных запросов и отслеживании ответов (например, для подачи в список). Вы можете написать 4 запроса и 4 обработчика ответа, но, поскольку у вас может быть больше запросов, вы можете написать асинхронный цикл. Классический цикл for состоит из init, условия и приращения. Вы можете разбить классический цикл for на цикл while и все равно быть эквивалентным. Затем вы превращаете цикл while в рекурсивную функцию. Теперь вы можете сделать это асинхронным. Я разместил несколько примеров сценариев здесь по адресу http://asynchronous.me/ . В вашем случае выберите цикл for в настройках. Если вы хотите, чтобы запросы отправлялись последовательно, то есть один запрос после предыдущего ответа (запрос1, ответ1, запрос2, ответ2, запрос3, ответ3 и т. Д.), Выберите Последовательная связь (т. Е. Последовательная), но код немного больше запутана. С другой стороны, если вас не волнует порядок получения ответов (случайный порядок), затем выберите Параллельное взаимодействие (т.е. одновременный), код будет более интуитивно понятным. В любом случае каждый ответ будет связан с соответствующим запросом по идентификатору (простое целое число), чтобы вы могли отслеживать их все. Сайт предоставит вам пример сценария. Примеры написаны на JavaScript, но это применимо к любому языку. Адаптируйте скрипт к вашему языку и настройкам кодирования. С помощью этого скрипта ваш браузер отправит 4 запроса асинхронно, и по идентификатору вы сможете отслеживать, какому запросу соответствует ответ. Надеюсь это поможет. / Тибо Лопес Шнайдер

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top