Xamarin HttpClient.Взаимоблокировка PostAsync

#android #multithreading #xamarin #httpclient #deadlock

#Android #многопоточность #xamarin #httpclient #взаимоблокировка

Вопрос:

У нас возникла проблема с классом System.Net.Http.HttpClient. Приведенный ниже код отлично работает со многими устройствами Android, за исключением некоторых, из которых два устройства перечислены ниже. Выполнение застревает на следующей строке, блокируя поток, из-за чего приложение перестает отвечать, что приводит к повышению ANR (приложение не отвечает).

 var resp = await client.PostAsync(url, content);
  

Затронутые устройства:
Samsung Note 9 (Android 9.0) и
Samsung S7 (Android 8.0)

Недавно мы обновили некоторые зависимости, которые требовались для обновления Google Maps и SMS Retriever API.

Вот исходный код:

 async void ExecuteLogin()
        {
            try
            {

                var isOperationSuccessful = await PerformServiceCall(async () =>
                {
                    await DependencyService.Get<DataStore.Abstractions.IAuthService>().LoginAsync(Username, Password.Encrypt());
                });
            }
            catch (Exception ex)
            {
            }
            finally
            {
            }
        } 


public async Task LoginAsync(string username, string password)
        {
            var response = await PostHelper.DoRequest<LoginRequest, LoginResponse>(ServiceURL.Login,
                new LoginRequest()
                {
                    UserId = username,
                    Password = password,
                });

            ApiResponseValidator.ValidateResponse(response, "Unable to login");

            GlobalHelper.SessionId = response?.SessionId;
            GlobalHelper.Username = username;
        } 




public static async Task<U> DoRequest<T,U>(string url, T obj)
        {
            var result = "{}";
            try
            {
                using (var client = new HttpClient())
                {
                    string datasent = JsonConvert.SerializeObject(obj);
                    HttpContent content = new StringContent(datasent,
                        Encoding.UTF8,
                        "application/json");
                    client.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident / 6.0)");

                    var resp = await client.PostAsync(url, content);
                    
                    result = resp.Content.ReadAsStringAsync().Resu<

                    return JsonConvert.DeserializeObject<U>(result);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Unable to service the request at this time. {ex.Message}", ex);
            }
        } 

protected async Task<bool> PerformServiceCall(Func<Task> serviceCallAction, 
            Action<GenericException> onError = null)
        {
            if (!CrossConnectivity.Current.IsConnected)
            {
                DisplayInfo("Looks like you're not connected to the internet.", "DISMISS", null);

                return false;
            }

            if (IsLoading)
            {
                return false;
            }

            try
            {
                IsLoading = true;
                await serviceCallAction?.Invoke();
                return true;
            }
            catch (GenericException ex) when (ex.ExType == ExceptionType.SessionTimeOut)
            {
                SessionTimedOut<BaseViewModel>();
                Logger.Report(ex, Severity.Error);
                return false;
            }
            catch (CriticalException ex)
            {
                if (onError != null)
                {
                    onError.Invoke(ex);
                }
                else
                {
                    DisplayCriticalInfo(ex.Title, ex.Message);
                }
                                
                Logger.Report(ex, Severity.Error);
                return false;
            }
            catch (GenericException ex)
            {
                if (onError != null)
                {
                    onError.Invoke(ex);
                }
                else
                {
                    DisplayInfo(ex.Message);
                }

                Logger.Report(ex, Severity.Error);
                return false;
            }
            catch (Exception ex)
            {
                DisplayInfo(ex.Message);
                Logger.Report(ex, Severity.Error);
                return false;
            }
            finally
            {
                IsLoading = false;
            }
        }  

Вот список пакетов с их версией для справки, определенной в packages.config в проекте Xamarin.

 <package id="ExifLib.PCL" version="1.0.1" targetFramework="portable-net45 win wpa81 MonoAndroid10 xamarinios10 MonoTouch10" />
  <package id="Microsoft.Bcl" version="1.1.10" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Plugin.Fingerprint" version="1.4.9" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Plugin.Permissions" version="2.0.1" targetFramework="portable45-net45 win8 wpa81" />
  <package id="sameerIOTApps.Plugin.SecureStorage" version="1.2.1" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Syncfusion.Xamarin.SfCalendar" version="14.3.0.49" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xam.Plugin.Connectivity" version="2.3.0" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xamarin.Build.Download" version="0.4.6" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xamarin.Forms" version="3.2.0.871581" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xamarin.Forms.CarouselView" version="2.3.0-pre2" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xamarin.Forms.GoogleMaps" version="3.0.4" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xamarin.Forms.Maps" version="2.3.4.247" targetFramework="portable45-net45 win8 wpa81" />
  <package id="Xamvvm.Forms" version="1.0.0" targetFramework="portable45-net45 win8 wpa81" />
  <package id="XLabs.Core" version="2.2.0-pre02" targetFramework="portable45-net45 win8 wpa81" />
  <package id="XLabs.Forms" version="2.2.0-pre02" targetFramework="portable45-net45 win8 wpa81" />
  <package id="XLabs.IoC" version="2.2.0-pre02" targetFramework="portable45-net45 win8 wpa81" />
  <package id="XLabs.Platform" version="2.2.0-pre02" targetFramework="portable45-net45 win8 wpa81" />
  <package id="XLabs.Serialization" version="2.2.0-pre02" targetFramework="portable45-net45 win8 wpa81" />   

Комментарии:

1. используйте await vs .Result при вызове ReadAsStringAsync

2. У меня такая же проблема — вы нашли решение?