AsyncTask, исключение RejectedExecutionException и Ограничение задачи
-
21-09-2019 - |
Вопрос
Я извлекаю множество эскизов с удаленного сервера и отображаю их в виде таблицы, используя AsyncTask.Проблема в том, что в моем представлении сетки одновременно отображается 20 миниатюр, так что создается 20 асинхронных задач и запускается 20 выполнений, по одной на миниатюру.
Я получаю RejectedExecution
исключение в моем коде.Я помню, что где-то читал, что существует ограничение на количество задач, которые AsyncTask может иметь в своей очереди одновременно, возможно, я ошибаюсь.Была ли поднята эта планка?
Есть ли способ увеличить этот лимит?Безопасно ли просто игнорировать это исключение?(имея пустой catch(RejectedException e){}
блокировать?)
Я запускаю этот код на эмуляторе Android 1.6 и уровне API в моем коде (minSdkVersion равен 3).[ПРАВИТЬ:Добавлена информация об уровне SDK и API]
Решение
Я помню, что где-то читал, что существует существует ограничение на количество задач, которые AsyncTask может иметь в своей очереди одновременно возможно, я достигаю этого.Была ли эта планка снята?
AsyncTask
похоже, в настоящее время поддерживается 10 потоков и глубина рабочей очереди 10.Теоретически, это просто поддерживало бы 20 элементов ... если больше ничего не используется AsyncTask
.
Есть ли способ увеличить этот лимит?
Возьмите исходный код, измените его, поместите в свой собственный пакет и используйте этот.Я сделал это с моим AsyncTaskEx
, хотя это основано на исходном коде Android 1.5.
Безопасно ли просто игнорировать это исключение?
Ваша работа не будет поставлена в очередь на выполнение.Является ли это "безопасным", зависит от вас.Я не осведомлен о каких-либо других воздействиях на AsyncTask
инфраструктура.
Другие советы
Я сам проделал то же самое в приложении.
Одновременный запуск 20 параллельных потоков для загрузки эскизов с сервера и отправки их в адаптер данных не кажется мне хорошей идеей.Все эти нити будут просто натыкаться друг на друга и мешать друг другу.
Вместо этого я бы запустил только один поток, попросил бы его собирать эскизы в цикле и добавлять их в адаптер по мере их поступления.
Вы могли бы использовать последовательный исполнитель с AsyncTask.executeOnExecutor для сериализации ваших задач, но это ограничит задачу только одной одновременной задачей в данный момент.Хотя это может быть полезно при получении миниатюр:
myAsyncTask.executeOnExecutor(MyAsyncTask.SERIAL_EXECUTOR, [параметры] );
Проблема в том, что количество ожидающий рассмотрения Асинхронные задачи для AsyncTask.THREAD_POOL_EXECUTOR
составляет 128.Как только очередь заполнена, никакие новые асинхронные задачи не могут быть поставлены в очередь.
Из исходного кода AsyncTask:
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
На мой взгляд, это ограничение вообще не имеет абсолютно никакого смысла, и AsyncTask.SERIAL_EXECUTOR
имеет неограниченную очередь.
"Безопасно" игнорировать - вам нужно убедиться, что любой вид уведомления, который вы планировали сделать после выполнения, будет выполнен здесь, когда вы поймаете ошибку - в противном случае вы можете оставить что-то зависшим, если ваш другой код делает предположения о получении ответа от этой задачи.