Domanda

Ho una pagina che deve combinare i dati di quattro diverse richieste web in un unico elenco di elementi. Attualmente, sto eseguendo questi in sequenza, aggiungendo a un unico elenco, quindi associando tale elenco al mio ripetitore.

Tuttavia, vorrei essere in grado di chiamare queste quattro richieste web in modo asincrono in modo che possano essere eseguite contemporaneamente e risparmiare tempo di caricamento. Sfortunatamente, tutti i tutorial e gli articoli asincroni che ho visto trattano una singola richiesta, usando il gestore finito per continuare l'elaborazione.

Come posso eseguire i quattro (questo potrebbe persino aumentare!) contemporaneamente, tenendo presente che ogni risultato deve essere inserito in un unico elenco?

molte grazie!

EDIT: esempio semplificato di ciò che sto facendo:

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;
} 
È stato utile?

Soluzione

Questo dovrebbe essere davvero semplice poiché i tuoi dati finali dipendono dal risultato di tutte e quattro le richieste.

Quello che puoi fare è creare 4 delegati asincroni ciascuno che punta al metodo web appropriato. Fai un BeginInvoke su tutti loro. E poi usa WaitHandle per aspettare tutto. Non è necessario utilizzare le richiamate, nel tuo caso, poiché non vuoi continuare mentre i metodi web vengono elaborati, ma piuttosto attendi che tutti i metodi web finiscano l'esecuzione.

Solo dopo l'esecuzione di tutti i metodi Web, verrà eseguito il codice dopo l'istruzione wait. Qui puoi combinare i 4 risultati.

Ecco un codice di esempio che ho sviluppato per te:

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

    }

Altri suggerimenti

Che ne dici di lanciare ogni richiesta sul proprio thread separato e quindi aggiungere i risultati all'elenco?

puoi testare questo codice seguente:

Parallel.Invoke (() = >                         {
                            // TODO esegue le tue richieste ...                         });

Sono necessarie estensioni parallele di riferimento: http://msdn.microsoft.com/en-us/concurrency/bb896007. aspx

@Josh: riguardo alla tua domanda sull'invio di 4 (potenzialmente più) richieste asincrone e sul monitoraggio delle risposte (ad esempio per alimentare un elenco). È possibile scrivere 4 richieste e 4 gestori di risposta, ma poiché potenzialmente si avranno più richieste, è possibile scrivere un ciclo asincrono. Un classico per ciclo è costituito da un init, una condizione e un incremento. Puoi scomporre un classico per loop in un ciclo while ed essere comunque equivalente. Quindi trasformi il ciclo while in una funzione ricorsiva. Ora puoi renderlo asincrono. Ho inserito alcuni script di esempio qui a http://asynchronous.me/ . Nel tuo caso, seleziona il ciclo for nelle opzioni. Se desideri che le richieste vengano inviate in sequenza, ovvero una richiesta dopo la risposta precedente (richiesta1, risposta1, richiesta2, risposta2, richiesta3, risposta3, ecc.), Scegli Comunicazione seriale (cioè sequenziale), ma il codice è un po 'più intricato. D'altra parte, se non ti interessa l'ordine in cui le risposte vengono ricevute (ordine casuale), quindi scegli Comunicazione parallela (cioè simultanea), il codice è più intuitivo. In entrambi i casi, ogni risposta sarà associata alla sua richiesta corrispondente da un identificatore (un intero semplice) in modo da poterne tenere traccia. Il sito ti fornirà uno script di esempio. Gli esempi sono scritti in JavaScript ma è applicabile a qualsiasi lingua. Adatta lo script alla tua lingua e alle tue preferenze di codifica. Con quello script, il tuo browser invierà 4 richieste in modo asincrono e tramite l'identificatore sarai in grado di tenere traccia di quale richiesta corrisponde la risposta. Spero che questo ti aiuti. / Thibaud Lopez Schneider

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top