AsyncTask, исключение ExjectException и ограничение задачи

Я извлекаю много эскизов с удаленного сервера и отображаю их в виде сетки, используя AsyncTask. Проблема в том, что мой сетчатый вид отображает 20 эскизов за раз, так что создает 20 AsyncTasks и запускает 20 исполнений, по одному на миниатюру.

Я получаю исключение RejectedExecution в моем коде. Я помню, что где-то читал, что существует ограничение на количество задач, которые AsyncTask может иметь в своей очереди за раз, возможно, это ударит. Был ли этот бар поднят?

Есть ли способ увеличить этот предел? Можно ли просто игнорировать это исключение? (Имея пустой блок catch(RejectedException e){}?)

Я запускаю этот код на эмуляторе Android 1.6 и уровне API в моем коде (minSDKVersion равно 3). [EDIT: добавлена ​​информация об уровне SDK и API]

Ответ 1

Я где-то вспоминаю, что там является пределом количества задач, которые AsyncTask может иметь в своей очереди время, я мог бы нанести удар. Был этот бар поднят?

AsyncTask, по-видимому, поддерживает 10 потоков и глубину рабочей очереди 10. Теоретически это будет поддерживать только 20 элементов... если ничего не использует AsyncTask.

Есть ли способ увеличить этот предел?

Возьмите исходный код, измените его, поместите в свой собственный пакет и используйте его. Я сделал это с помощью AsyncTaskEx, хотя он основан на источнике Android 1.5.

Безопасно ли просто игнорировать это исключение?

Ваша работа не будет поставлена ​​в очередь для выполнения. Независимо от того, является ли это "безопасным", зависит от вас. Я не знаю никаких других воздействий на инфраструктуру AsyncTask.

Ответ 2

Я сделал то же самое сам в приложении.

Запуск 20 параллельных потоков одновременно для загрузки эскизов с сервера и их подталкивания к адаптеру данных не кажется мне хорошей идеей. Все эти потоки будут просто путешествовать друг на друга и вступать друг в друга.

Вместо этого я бы запускал только один поток, собирал миниатюры в цикле и добавлял их в адаптер по мере их поступления.

Ответ 3

Вы можете использовать последовательный исполнитель с AsyncTask.executeOnExecutor, чтобы сериализовать ваши задачи, но это ограничивает задачу только одной одновременной задачей в то время. Может быть хорошо, хотя при получении миниатюр:

myAsyncTask.executeOnExecutor(MyAsyncTask.SERIAL_EXECUTOR, [params]);

Ответ 4

Проблема заключается в том, что количество ожидающих AsyncTasks для AsyncTask.THREAD_POOL_EXECUTOR равно 128. После заполнения очереди новые AsyncTasks могут быть поставлены в очередь.

Из исходного кода AsyncTask:

private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

По-моему, этот лимит совершенно не имеет смысла, а AsyncTask.SERIAL_EXECUTOR имеет неограниченную очередь.

Ответ 5

"Безопасный", чтобы игнорировать - вам нужно убедиться, что любое уведомление, которое вы планируете делать в post-execute, будет сделано здесь, когда вы поймаете ошибку - иначе вы можете оставить что-то висящее, если ваш другой код делает предположения о том, чтобы услышать от этой задачи.