Nano Hash - криптовалюты, майнинг, программирование

Вызов Looper более одного раза приводит к отправке сообщения обработчику в мертвом потоке.

Я использую Executor [фиксированный пул потоков] с моей собственной ThreadFactory, которая добавляет Looper:

Handler HANDLER = new Handler();
Executor    THREADS = Executors.newFixedThreadPool(THREAD_POOL_SIZE, new ThreadFactory() {
    @Override public Thread newThread(Runnable runnable) {
        return new MyThread(new Runnable() {
            @Override public void run() {
                Looper.prepare();
                runnable.run();
            }
        });
    }
});

private static class MyHandler extends Handler {
    public boolean fail;
        public void handleMessage(Message msg) {
        switch(msg.what) {
            case 1:
                this.fail = msg.arg1 == 1;
                Looper.myLooper().quit();
                break;
            }
        }
    }
}

Я запускаю поток, который делает сетевые запросы, но если сеть дает сбой, я бы хотел, чтобы пользователю отображалось диалоговое сообщение. Этот процесс довольно сложный, поскольку он требует выполнения И отображения запроса в потоке пользовательского интерфейса. Я могу дождаться ответа пользователя на диалоговое окно, просто добавив цикл в сетевой поток и дождаться отправки сообщения из потока пользовательского интерфейса. Это позволяет мне инкапсулировать сетевые запросы в потоке while(tryAgain). Все работает хорошо, за исключением случаев, когда метод Looper.loop() вызывается во второй раз (после отображения второго диалогового окна сетевой ошибки) и диалоговое окно (в потоке пользовательского интерфейса) отправляет сообщение обработчику сетевого потока:

THREADS.execute(new Runnable() {
    private MyHandler   myHandler   = new MyHandler();
    @Override public void run() {
        boolean tryAgain    = true;
        while(tryAgain) {
            try {
                switch(request) {
                    [Handle network requests]
                }
                tryAgain    = false;

            } catch(IOException e) {
                // The network is unavailable.  Ask the user if we should try again.
                e.printStackTrace();

            } finally {
                if(tryAgain) {
                    HANDLER.post(new Runnable() {   // The UI thread
                        @Override public void run() {
                            theAlertDialog.show();
                        }
                    });

                    // Wait for the results from the dialog which lives in the UI thread.
                    Looper.loop();

                    // At this point the dialog has informed us of our answer.
                    tryAgain = !myHandler.fail;
                }
            }
        }
    }
});

В экземпляре AlertDialog есть OnClickListener:

DialogInterface.OnClickListener myOnclickListener = new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int id) {
        Message msg = myHandler.obtainMessage(1);
        msg.setTarget(this.handler);
        msg.sendToTarget();
    }
}

Я проверил, что поток все еще активен с помощью handler.getLooper().getThread().isAlive(), который всегда возвращает true, но все равно дает мне «отправить сообщение обработчику в мертвом потоке». Как получается, что сообщение/обработчик решил, что поток мертв? Разве он не должен полагаться на метод .isAlive()? В конце концов, я пытаюсь избежать репликации сборки управления потоками в ОС Android :-)


Ответы:


1

Если вы проверите источник в android/os/MessageQueue.java, вы увидите что-то вроде следующего

  if (mQuiting) {
                RuntimeException e = new RuntimeException(
                    msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                return false;
            } else if (msg.target == null) {
                mQuiting = true;
            }
   }

Таким образом, очередь сообщений в основном непригодна для использования после того, как Looper.quit() был вызван в первый раз, поскольку он ставит в очередь сообщение с нулевой целью, которая является волшебным идентификатором для очереди сообщений, чтобы прекратить постановку в очередь и казаться «мертвым».

23.11.2010
  • хех, извините за ответ с опозданием на год. Я не уверен, что получил уведомление об этом :-/ 11.09.2012

  • 2

    См. http://code.google.com/p/android/issues/detail?id=20915, что, возможно, является основной причиной проблемы. Он включает в себя обходной путь для этой проблемы.

    18.10.2011
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..