3

Мое приложение iPad разработано в MonoTouch, потому что я хотел избежать всего адмирала памяти, но это не похоже на ситуацию. На симуляторе все работает нормально, но когда я тестировал свое приложение на устройстве, я с ужасом обнаружил, что он быстро убивается ОС после некоторых предупреждений о памяти. Мое приложение - это простой браузер изображений, он загружает некоторые изображения PNG и показывает их, используя некоторые UIView внутри UIScrollView, загружая следующий или предыдущий при получении прикосновения. На симуляторе он отлично работает. Но на устройстве после загрузки и разгрузки около 6-11 изображений он начинает получать предупреждения о памяти, а затем внезапно процесс уничтожается. Я проверил все свои циклы, и я правильно удалю все ссылки перед загрузкой новых изображений.MonoTouch: приложение убито за низкую память, почему? Распределение живых байтов 5 МБ top

Итак, я начал работу с инструментами и начал профилировать выделение памяти моего приложения на iPad. Там я обнаружил, что байты Live составляют всего около 5-9 МБ, только то, что я ожидал, но по какой-то странной причине объем мертвой памяти почти не собран, потому что после выделения около 50 МБ (менее 5-9 МБ это Live Bytes), он убит! Вот скриншот из инструментов профилирования сессии моего приложения:

Instruments screenshots documenting memory allocation problem under monotouch

А вот последовательность heapshots:

heapshots of my app in instruments

Есть также некоторые небольшие утечки, но я думаю, что они недостаточно велики, чтобы быть виновниками. Они все 48 байт утечки из strdup, известная проблема при выпуске UIScrollView в прошивкой 5.1:

enter image description here

Даже со всем, что кажется нормально и Текущий Bytes выделенный по-прежнему на 5 Мб, реальная память о моем приложение растет в геометрической прогрессии, прежде чем убить до 50Мб на IPAD, и до 314 МБ на iPhone4S, как сообщает Monitor Memory:

memory growth of my App on iPhone4S

ли кто-нибудь может сказать мне, если есть способ, или полезности, чтобы узнать, что и где проблема? Это ошибка сборщика мусора monotouch? Или есть какой-то объект, который я не правильно распоряжаюсь? И как я могу найти тех, у кого есть профилировщик? Я проверил свой код на два дня, но все кажется правильным.

Вот мой код для загрузки/инстансов/располагающий цикла:

void StartImageLoadingThread() 
{ 
    tokenSource = new CancellationTokenSource(); 
    token = tokenSource.Token; 
    Task task1 = new Task(() => PerformLoadImageTask(token),token); 
    task1.Start(); 
} 


void PerformLoadImageTask(CancellationToken token) 
{ 
     if (token.IsCancellationRequested) 
       { 
        Console.WriteLine("Task {0}: Cancelling", Task.CurrentId); 
       return; 
       } 

      current_uiimage_A = UIImage.FromFileUncached(file_name); 
      page_A_image_view.Image = current_uiimage_A; 


} 


void UnloadImageAFromMemory() 
{ 
     page_A_image_view.Image = null; 
     current_uiimage_A.Dispose(); 
     current_uiimage_A = null; 
} 

Есть ли способ, чтобы поймать объект, который не был правильно расположенными? Инструменты сообщают, что живые байты являются низкими, утечки почти равны нулю, то почему мертвые объекты не удаляются? Даже если ничего не происходит в моем приложении в течение нескольких минут, GC, похоже, не делает его работу, даже если я назову ее экспликацией в моем коде. Я даже попробовал новый экспериментальный сборщик мусора, но еще хуже и быстрее сделать мое приложение убитым.

Невозможно найти руководство или пошаговое руководство на веб-сайте Xamarin для устранения неполадок с памятью или устранения неправильных распределений.

Любая помощь или предложение очень ценится, Спасибо!

ОБНОВЛЕНИЕ: Я уменьшил размер и разрешение некоторых изображений и uiviews, а Live Bytes теперь сброшены с 9 МБ до 5 МБ, но приложение все еще убито после некоторых предупреждений о памяти, независимо от того, что ,

ОБНОВЛЕНИЕ 2: Как предложил Хавьер, я удалил фоновые задачи и сделал прямые звонки, и утечка памяти исчезла! Кажется, что сборщик мусора MonoTouch имеет ошибку и не может собирать память, когда UIImages распределены и расположены в другом потоке. Но теперь мое приложение ужасно не отвечает, когда я прокручиваю, поэтому мне нужно найти решение, чтобы сделать это в другом потоке! Но как?

ответ

2

У меня были проблемы с UIImage.FromFile. Мое приложение загружает много png-изображений с помощью задачи и показывает ее в основном потоке.

Я добавил GC.Collect в фоновое задание, но это не устранило проблему. Мне пришлось удалить фоновое задание, сделать все содержимое основного потока и позвонить GC.Collect. Кажется, что Image.Dispose не отпуская память изображений :(

Но это не работает, если у вас есть другая задача, поэтому я должен был удалить его :(

Да это не работает ...

+0

Вы правы! Я удалил фоновые задачи и сделал прямые звонки, и утечка памяти исчезла! Похоже, что сборщик мусора MonoTouch имеет ошибку, когда UIImages выделяются в другом потоке. Но теперь мое приложение не отвечает, когда я прокручиваю, поэтому мне нужно найти решение, чтобы сделать это в другом потоке! Но как? –

+0

Ну, вы можете заполнить ошибку в https://bugzilla.xamarin.com/. Мой английский не очень хорош, я боюсь, что они меня не очень хорошо понимают ... :( –

+0

Я считаю, что они знают об ошибке. Я читал, что бета-версия MonoTouch 5.3 имеет некоторые проблемы с некоторыми проблемами многопоточности UIKit Давайте подождем и посмотрим, устранит ли она нашу проблему. –

1

Это интересно для меня, я только начинаю смотреть на управление памятью, я даже не уверен, что это важно для нулевого и объектного вызова и вызова, потому что правила обзора должны выполнять эту работу за вас? это поможет сборщику мусора сделать это как можно скорее.

Явно запрашиваю, чтобы сборщик мусора запускал запрос, а не гарантию.

Я хотел бы угадать, что объект, созданный на нити ui, ссылается на один за пределами нити ui и будет выглядеть там, но я не уверен.

Я с нетерпением жду встречи с обновлением, так как я уверен, что у меня возникнут подобные проблемы!

Успехов, Роб

+0

Да, все работает правильно. MonoTouch GC должен автоматически распоряжаться всеми в конце области. Это похоже на то, что все методы уже были завернуты в AutoreleasePool за занавесками. Но почему-то, когда несколько потоков происходят в графических и пользовательских потоках, все эти автоматические вещи о сборе мусора перестают работать. Вы правы в том, что ссылаетесь на что-то в разных потоках. UIImage и UIImageView являются полями данных в основном потоке. Но почему, если я ссылаюсь на что-то в другом потоке, это не мусор, собранный, когда я распоряжаюсь им (даже эксцессом!)? –

3

Вы должны использовать NSAutoreleasePools вокруг кода создания образа, что-то вроде этого:

void PerformLoadImageTask(CancellationToken token) 
{ 
    if (token.IsCancellationRequested) 
    { 
     Console.WriteLine("Task {0}: Cancelling", Task.CurrentId); 
     return; 
    } 

    using (var pool = new NSAutoreleasePool()) { 
     current_uiimage_A = UIImage.FromFileUncached(file_name); 
     page_A_image_view.Image = current_uiimage_A; 
    } 
} 

Для некоторых API, которые создают объекты, объект будет добавлен в autorelease бассейн , и не отпускается до тех пор, пока пул не будет слит. MonoTouch автоматически создает пулы автозаполнения для всех пользовательских потоков (включая threadpool, TPL и обычные потоки System.Threading), но эти пулы не сливаются, пока поток не выйдет (который вы не можете контролировать в случае потоков threadpool и TPL). Таким образом, решение заключается в использовании NSAutoreleasePool вокруг критического кода (пул будет автоматически слит при удалении).

+0

Да и нет. Много раз AutoreleasePools работает, но не в этот раз. Я пробовал, но он не работает. Единственное, что останавливает выделение от роста, - это удаление любого использования вторичных протекторов. Затем распределение памяти является стабильным и постоянным, и приложение больше не сработает. Использование пулов Autorelease не изменяет скорость или количество распределения вообще. Я думаю, что это ошибка от GC MonoTouch или что-то вроде ограничения в обработке классов UIKit во вторичных потоках. –

+0

@ EmanueleSabetta: если вы считаете, что это ошибка в GC MonoTouch (или, в противном случае, проблема внутри MonoTouch), вы должны указать ошибку (http://bugzilla.xamarin.com) с тестовым примером. –

+0

Отлично работает сейчас !!!! Использование NSAutoreleasePool и GC.Collect в фоновом задании работает на меня. Благодаря!!!! –

 Смежные вопросы

  • Нет связанных вопросов^_^