Pergunta

Eu tenho uma página que precisa combinar dados de quatro webrequests diferentes em uma única lista de itens. Atualmente, eu estou correndo estes sequencialmente, anexando a uma única lista, em seguida, ligação essa lista ao meu repetidor.

No entanto, eu gostaria de ser capaz de chamar estas quatro webrequests de forma assíncrona, para que possam ser executados simultaneamente e economizar tempo de carga. Infelizmente, todos os tutoriais assíncronos e artigos que eu vi lidar com um único pedido, usando o manipulador acabado para continuar o processamento.

Como posso executar a quatro (Isso pode até aumentar!) Ao mesmo tempo, tendo em mente que cada resultado tem de ser alimentado em uma única lista?

muito obrigado!

EDIT: simplificado exemplo do que eu estou fazendo:

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;
} 
Foi útil?

Solução

Isto deve ser muito simples, já que os seus dados final depende do resultado de todos os quatro pedidos.

O que você pode fazer é criar 4 assíncronos delegados cada um apontando para o método da Web apropriado. Fazer um BeginInvoke em todos eles. E então usar um WaitHandle para aguardar para todos. Não há necessidade de chamada costas utilização, no seu caso, como você não quer continuar enquanto os métodos da web estão sendo processados, mas sim esperar até todos os métodos da web terminar execução.

Somente após todos os métodos da web são executadas, será o código após a declaração de espera executar. Aqui você pode combinar os 4 resultados.

Aqui está um exemplo de código que eu desenvolvi para você:

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";
        }

    }

Outras dicas

Como sobre o lançamento de cada pedido em seu próprio segmento separado e, em seguida, acrescentar os resultados para a lista?

Você pode testar este código a seguir:

Parallel.Invoke (() => {
// TODO executar seus pedidos ... });

Você precisa referenciar extensões paralelas: http://msdn.microsoft.com/en-us/concurrency/bb896007. aspx

@ Josh: Quanto à sua pergunta sobre o envio de 4 (potencialmente mais) solicitações assíncronas e manter o controle das respostas (por exemplo, para alimentar em uma lista). Você pode escrever 4 pedidos e 4 manipuladores de resposta, mas já que você vai ter, potencialmente, mais pedidos, você pode escrever um loop assíncrono. Um clássico para o laço é feito de uma inicialização, uma condição, e um incremento. Você pode quebrar um clássico loop em um loop while e ainda ser equivalente. Então você faz o loop while em uma função recursiva. Agora você pode fazê-lo assíncrona. Eu coloquei alguns exemplos de scripts aqui em http://asynchronous.me/ . No seu caso, selecione o loop for nas opções. Se desejar que os pedidos sejam enviados em seqüência, ou seja, um pedido após a resposta anterior (pedido1, response1, request2, response2, request3, response3, etc.), em seguida, escolher de comunicação serial (ie seqüencial), mas o código é um pouco mais intrincada. Por outro lado, se você não se preocupam com a ordem em que as respostas são recebidas (ordem aleatória), em seguida, escolha a comunicação paralela (ou seja concorrente), o código é mais intuitivo. Em ambos os casos, cada resposta será associado a seu pedido correspondente por um identificador (um inteiro simples) para que você possa manter o controle de todos eles. O site vai lhe dar um exemplo de script. As amostras são escritos em JavaScript, mas é aplicável a qualquer idioma. Adaptar o roteiro para o seu idioma e as preferências de codificação. Com esse script, o navegador enviará 4 pedidos de forma assíncrona, e pelo identificador que você vai ser capaz de acompanhar o que pedir aos corresponde resposta para. Espero que isto ajude. / Thibaud Lopez Schneider

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top