2017-01-21 1 views
4

J'ai une méthode qui exécute plusieurs requêtes HTTP appelées LoadServers() Un bouton qui exécute LoadServers(). Pour mon problème, je n'appuie que sur le bouton une fois l'appel LoadServers() terminé. Une boîte de dialogue de progression apparaît pendant le chargement afin que je puisse seulement les exécuter en série.Xamarin.Android HTTP Random Delays

Une fois environ tous les 10-15 appels à LoadServers résultats dans la première requête http à retarder pendant presque exactement 10 secondes. Le délai moyen pour compléter LoadServers est inférieur à une demi-seconde et ne dépasse jamais 1 seconde. Cela n'arrive que sur Xamarin.Android. Le retard n'arrive pas sur Xamarin.iOS et tout ce code est partagé.

Voici mon code

private async Task LoadServers() { 
    await Get(); 
    await Post(); 
    await Get(); 
    await Get(); 
    await Post(); 
} 

private async Task Get() { 
    var url = _httpClient.BaseAddress + model.GetToken(); 
    Log("Attempting to send GET to: " + url); 
    using (var response = await _httpClient.GetAsync(url)) 
    { 
     var resultContent = await response.Content.ReadAsStringAsync(); 
     Log("Got response back from : " + url + ": " + resultContent); 
    } 
} 

private async Task Post() { 
    var content = requestData.GetToken() + "=" + requestData.PostBody(); 
    var request = new StringContent(content) 
    { 
     Headers = { ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded") } 
    }; 
    var url = _httpClient.BaseAddress + "/No_content"; 
    Log ("Attempting to send POST to: " + url + " with content: " + content); 
    using (var response = await _httpClient.PostAsync(url, request)) 
    { 
     string resultContent = await response.Content.ReadAsStringAsync(); 
     Log("Got response back from : " + url + ": " + resultContent); 
    } 
} 

Chaque 15 ou si les exécutions de LoadServers() résultats dans les états journaux suivants:

Thread started: #37 
Thread finished: #37 
[2017-01-21T13:42:30.8841620-06:00] [debug] Loading Servers 
[2017-01-21T13:42:30.8946770-06:00] [debug] Attempting to send GET to: XXX 
Thread finished: <Thread Pool> #23 
Thread started: <Thread Pool> #38 
[2017-01-21T13:42:40.9550360-06:00] [debug] Got response back from : XXX <-- Notice the time (~10 seconds) 

Est-ce que cela a à voir avec la consommation de ressources pour la requête HTTP? Il tente de nettoyer les ressources et suspendre l'exécution jusqu'à ce que cela se produise? Je ne suis pas sûr exactement ce qui se passe quand il exécute la demande. Est-ce qu'il commence un nouveau fil?

+0

Je ne peux pas reproduire votre problème, mais je l'ai trouvé deux problèmes avec votre code. 1. Puisque vous faites du thread dans vos méthodes 'Get()' et 'Post()' en utilisant le mot clé 'await', alors ces deux méthodes devraient être' async'. 2. ces deux méthodes ne sont pas des tâches et elles sont nulles, vous n'avez pas besoin/ne pouvez pas les 'attendre' dans votre tâche 'LoadServers'. Je ne sais pas comment vous faites fonctionner votre code, à mes côtés, j'ai besoin de modifier votre code mais je n'ai toujours pas pu reproduire votre problème. Pour isoler le problème du périphérique, vous pouvez utiliser un émulateur ou un autre périphérique Android pour tester votre code. –

+0

Salut @ GraceFeng-MSFT, Merci pour la réponse. Comme je nettoyais le code, j'ai accidentellement mis ceux-ci comme des vides au lieu de 'Task '. J'ai édité la question. C'est sur un réseau local et se connecter à un périphérique local.Ainsi, le temps nécessaire à l'appareil pour répondre est de 10 à 30 millisecondes. Cela se produit sur de nombreux appareils différents et de nombreux niveaux d'API OS Android différents. Comme cela ne se passe pas sur iOS avec exactement le même code, je pense que c'est quelque chose avec Android. – kevskree

+0

@kevskree, essayez d'exécuter le même code dans une application de console sur votre Mac pour supprimer les SDK mobiles de l'équation. Ensuite, déposez un problème sur https://bugzilla.xamarin.com/enter_bug.cgi?product=Android avec l'échantillon que nous pouvons utiliser pour essayer de reproduire. Vous pouvez inclure un exemple en tant que pièce jointe privée. Incluez tous les détails dont nous pourrions avoir besoin pour le configurer localement. – therealjohn

Répondre

2

Déterminer le problème exact est difficile, et je suis incapable de le reproduire. Toutefois, l'emballage de System.Net et le MessageHandler par défaut dans le HttpClient n'est pas complètement optimisé. Donc, votre supposition que c'est un problème de ressources pourrait être le cas.

Essayez d'utiliser ModernHttpClient (Xamarin Component | Nuget | Developer Review | Github), et en ajoutant le NativeMessageHandler dans le constructeur pour vous HttpClient. Cela va utiliser les bibliothèques natives optimisées (pour Android, c'est OkHttp) ce qui aidera les performances.

+0

N'ont-ils pas essentiellement construit ModernHttpClient dans la dernière version de Xamarin.Android? –

+0

Ils ont augmenté ses performances, mais 'OkHttp' va encore plus loin. Aussi, ce ne serait que lors de l'appel du code du projet Xamarin.Android, pas d'un PCL. Le PCL utilisera le HttpClient .NET Portable intégré qui n'utilise pas le nouveau gestionnaire. – SuavePirate

+0

Oh cool, ne s'est pas rendu compte. Je vais continuer à l'utiliser ensuite :) –

0

J'ai expérimenté le même problème. J'utilise xamarin.android 6.6.1.2-21 et des trucs de soutien 23. Api

J'ai trouvé que l'utilisation du par défaut HTTPHandler et la création de 2 httpClients avant votre premier appel à résoudre ce problème.

new HttpClient(new Xamarin.Android.Net.AndroidClientHandler()); 

et créer 2 httpclients commencent avant tout appel réel dans votre code.

Configurez également "Implémentation HttpClient" sur "AndroidClientHandler". Vous pouvez trouver cette option sur: Options du projet> Construire Android> Génération de code et Runtime. Ce ne fonctionne que sur Android 5+

http implementation option

+0

Vous voulez simplement appeler '' 'var client = new HttpClient (new Xamarin.Android.Net.AndroidClientHandler()); client = new HttpClient (nouveau Xamarin.Android.Net.AndroidClientHandler()); '' ' résolu le problème? – kevskree

+0

formatez vos codes. https://meta.stackoverflow.com/questions/251361/how-do-i-format-my-code-blocks – IsuruAb

+0

Oui. Créez deux httpclient avant de créer le httpClient que vous utiliserez pour faire 'getAsync()' ou 'postAsync()'. Configurez également "Implémentation HttpClient" sur "AndroidClientHandler". Vous pouvez trouver cette option dans les options du projet> Android build> Génération de code et Runtime. –