несколько веб-запросов асинхронно в asp.net?
-
05-07-2019 - |
Вопрос
У меня есть страница, на которой необходимо объединить данные из четырех разных веб-запросов в один список элементов. В настоящее время я запускаю их последовательно, добавляю в один список, а затем связываю этот список с моим повторителем.
Однако я хотел бы иметь возможность вызывать эти четыре веб-запроса асинхронно, чтобы они могли выполняться одновременно и экономить время загрузки. К сожалению, все асинхронные учебники и статьи, которые я видел, имеют дело с одним запросом, использующим готовый обработчик для продолжения обработки.
Как я могу выполнить четыре (это может даже увеличиться!) одновременно, помня о том, что каждый результат должен быть введен в один список?
большое спасибо!
РЕДАКТИРОВАТЬ: упрощенный пример того, что я делаю:
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 запроса асинхронно, и по идентификатору вы сможете отслеживать, какому запросу соответствует ответ. Надеюсь это поможет. / Тибо Лопес Шнайдер