Question

J'ai une page qui doit combiner les données de quatre requêtes en ligne dans une seule liste d'éléments. Actuellement, je les exécute séquentiellement, en ajoutant à une liste unique, puis en liant cette liste à mon répéteur.

Toutefois, j'aimerais pouvoir appeler ces quatre requêtes en ligne de manière asynchrone afin qu'elles puissent s'exécuter simultanément et gagner du temps de chargement. Malheureusement, tous les didacticiels et articles asynchrones que j'ai vus traitent d'une seule demande et utilisent le gestionnaire fini pour poursuivre le traitement.

Comment puis-je effectuer les quatre (cela peut même augmenter!) simultanément, en gardant à l'esprit que chaque résultat doit être introduit dans une liste unique?

merci beaucoup!

EDIT: exemple simplifié de ce que je fais:

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;
} 
Était-ce utile?

La solution

Cela devrait être très simple car vos données finales dépendent du résultat des quatre requêtes.

Vous pouvez créer 4 délégués asynchrones pointant chacun sur la méthode Web appropriée. Faites un BeginInvoke sur chacun d'eux. Et ensuite, utilisez un WaitHandle pour tout attendre. Dans votre cas, il n’est pas nécessaire d’utiliser des rappels car vous ne souhaitez pas continuer pendant le traitement des méthodes Web, mais attendez que toutes les méthodes Web aient terminé leur exécution.

Ce n'est qu'après que toutes les méthodes Web ont été exécutées que le code après l'instruction wait sera exécuté. Ici, vous pouvez combiner les 4 résultats.

Voici un exemple de code que j'ai développé pour vous:

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

    }

Autres conseils

Pourquoi ne pas lancer chaque requête sur son propre thread séparé, puis ajouter les résultats à la liste?

vous pouvez tester le code suivant:

Parallel.Invoke (() = >                         {
                            // TODO Exécuter vos demandes ...                         });

Vous avez besoin d’extensions parallèles de référence: http://msdn.microsoft.com/en-us/concurrency/bb896007. aspx

@Josh: En ce qui concerne votre question sur l'envoi de 4 (potentiellement plus) de demandes asynchrones et le suivi des réponses (par exemple pour alimenter une liste). Vous pouvez écrire 4 demandes et 4 gestionnaires de réponses, mais puisque vous aurez potentiellement plus de demandes, vous pouvez écrire une boucle asynchrone. Une boucle for classique est composée d'un init, d'une condition et d'un incrément. Vous pouvez décomposer une boucle for classique en une boucle while tout en restant équivalente. Ensuite, vous faites la boucle while en une fonction récursive. Maintenant, vous pouvez le rendre asynchrone. Je mets quelques exemples de scripts ici, à l'adresse http://asynchronous.me/ . Dans votre cas, sélectionnez la boucle for dans les options. Si vous souhaitez que les requêtes soient envoyées en séquence, c'est-à-dire une requête après la réponse précédente (request1, response1, request2, response2, request3, response3, etc.), choisissez Communication série (c'est-à-dire séquentielle), mais le code est un peu plus complexe. D'autre part, si vous ne vous souciez pas de l'ordre dans lequel les réponses sont reçues (ordre aléatoire), choisissez ensuite Communication parallèle (c'est-à-dire simultanée), le code est plus intuitif. Dans les deux cas, chaque réponse sera associée à sa demande correspondante par un identifiant (un entier simple) afin que vous puissiez les suivre toutes. Le site vous donnera un exemple de script. Les exemples sont écrits en JavaScript mais s’appliquent à toutes les langues. Adaptez le script à votre langue et à vos préférences de codage. Avec ce script, votre navigateur enverra 4 demandes de manière asynchrone, et vous pourrez suivre l’identificateur de la demande à laquelle correspond la réponse. J'espère que cela t'aides. / Thibaud Lopez Schneider

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top