Потоковый писатель.Запись зависает при записи большой строки, но операция API завершается успешно

#c# #xamarin #xamarin.forms #aws-lambda #streamwriter.write

Вопрос:

У меня есть приложение xamarin forms, которое выполняет вызовы API, и когда вызовы api включают очень маленькие строки json, они работают идеально. Примером полезной нагрузки, которая работает, является:

 {"command":"","route":"check_password","password":"password","sqlctype":"","service":"",data:""}
 

Примером полезной нагрузки, которая не работает, является:

 {"command":"","route":"run_script","password":"","sqlctype":"","service":"Image_Processor",data:"base64 string that is 2MB in size"}
 

Однако со второй полезной нагрузкой StreamWriter не успевает ее записать и зависает на неопределенный срок. Мой код здесь:

             using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                string json = "{"command":"","  
                              ""route":"" route ""," 
                              ""password":"" password "","  
                              ""sqlctype":"","  
                              ""service":"" service "","  
                              ""data":"" data ""}";

                streamWriter.Write(json);
            }
 

Но самое интересное заключается в том, что операция API успешно завершается в обоих случаях

Журналы cloudwatch для запуска с первой полезной нагрузкой выглядят следующим образом:

 START RequestId: ee583521-f17d-4143-9c27-031ab781ddae Version: $LATEST
END RequestId: ee583521-f17d-4143-9c27-031ab781ddae
REPORT RequestId: ee583521-f17d-4143-9c27-031ab781ddae Duration: 7.01 ms Billed Duration: 8 ms Memory Size: 128 MB Max Memory Used: 93 MB XRAY TraceId: 1-611ac895-4ba33ffa6e181b6e66821bfc...
 

С возвращенным телом

 "T"
 

Журналы cloudwatch для запуска со второй полезной нагрузкой выглядят следующим образом:

 START RequestId: d78b16de-1a0b-4b35-877a-2fd6437dcd71 Version: $LATEST
END RequestId: d78b16de-1a0b-4b35-877a-2fd6437dcd71
REPORT RequestId: d78b16de-1a0b-4b35-877a-2fd6437dcd71 Duration: 4159.55 ms Billed Duration: 4160 ms Memory Size: 128 MB Max Memory Used: 93 MB XRAY TraceId: 1-611ac940-61cca9b762d1a2ff6...
 

С возвращенным телом

 "[{"typ": "barcode", "outp": "0882658000546", "ymax": "0.6736111111111112", "ymin": "0.550843253968254", "xmax": "0.6736111111111112", "xmin": "0.3488756613756614"}, {"typ": "barcode", "outp": "A-0020-Z", "ymax": "0.4595734126984127", "ymin": "0.40153769841269843", "xmax": "0.6008597883597884", "xmin": "0.3194444444444444"}, {"typ": "barcode", "outp": "A-0010-Z", "ymax": "0.34077380952380953", "ymin": "0.29092261904761907", "xmax": "0.5929232804232805", "xmin": "0.328042328042328"}]"
 

Поскольку API явно работает и успешно работает в обоих случаях, почему приложение может зависать на

 streamWriter.Write(json)
 

имея только вторую полезную нагрузку?

Также может быть полезно отметить, что я тоже пытался сделать это асинхронно, и это зависало на клиенте.postasync независимо от полезной нагрузки (ни одна полезная нагрузка не зависала). Код:

         async Task<string> asyncAPI(string route, string password = "", string data = "", string service = "")
        {
            HttpClient client = new HttpClient();
            Uri uri = new Uri("https://uidvxrcio9.execute-api.us-east-2.amazonaws.com/default/Blueline_General_API");
            string json = JsonConvert.SerializeObject(new APIrequest(default, route, password, default, service, "dawdasdqwd2"));
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            client.DefaultRequestHeaders.Add("x-api-key", "key");
            HttpResponseMessage response = null;
            response = await client.PostAsync(uri, content);
            return await response.Content.ReadAsStringAsync();
        }
 

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

1. Декодирование base64 такого размера по своей природе связано с ЦП. Мобильные телефоны имеют очень символический процессор. Так что на самом деле это может быть то, сколько времени это займет. Вы пробовали некоторые промежуточные размеры данных, которые больше 0, но меньше 2 Мбайт?

2. Декодирование не выполняется по телефону. Кодирование выполнено, а затем полученная строка base64 записывается в поток запросов HttpWebRequest и отправляется в API.

3. @OwenBurns «зависает на неопределенный срок» ? Выполняется ли эта работа в потоке, не относящемся к пользовательскому интерфейсу? Убивает ли ОС приложение через ANR? Каково текущее состояние процесса? Что там внутри logcat ?

4. 2 МБ-это немного. Проблема почти наверняка не в потоковом писателе. В качестве теста сначала прочитайте поток запросов в строку в памяти. Держу пари, что именно это и висит. Что еще более важно, сделайте это в фоновом потоке — веб-ответ, должно быть, занял слишком много времени, вызвал некоторые проблемы в основном потоке. Вы искали в выводе отладки предупреждения или ошибки?

5. В окне отладки нет ничего, кроме потоков, которые открываются и затем закрываются. Я не уверен, как проверить статус процесса, и я не уверен, что означает ANR. Он выполняется в блокирующем потоке. Я добавил вывод logcat к вопросу.

Ответ №1:

Почему вы пытаетесь сериализовать свой собственный код? Используйте Newtonsoft.Пакет Json nuget и используйте методы, описанные в нем. Когда вы устанавливаете их, вы можете легко сериализовать все общедоступные свойства класса. Код для сериализации одного из ваших классов выглядит следующим образом:

 JsonConvert.SerializeObject(myCompany)
 

Если вы пытаетесь сериализовать необработанные данные….вы можете создать свойство byte[] в своем классе, например:

 public byte[] MyBytes {get; set;}
 

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

1. хотя это хороший момент, он не должен иметь никакого отношения к тому, отказывает или нет StreamWriter.Write()

2. Возможно….но является ли этот раздел текста выше допустимым json? ,данные:»строка base64 размером 2 МБ»} В поле данных нет кавычек….

3. Я использую плагин просмотра json в Notepad , и он не будет форматировать этот текст в формате json: {«команда»:»»,»маршрут»:»run_script»,»пароль»:»»,»тип sqlc»:»»,»служба»:»Обработчик изображений», данные: «строка base64 размером 2 МБ»} В нем говорится, что json недействителен.

4. Я не уверен, как JSON может быть недействительным, когда небольшие запросы работают должным образом. Не будет ли неправильный JSON означать, что код вообще не будет работать?

5. Я попробовал это сейчас, и это не решило мою проблему.