Почему мой Swingworker отменяет свой поток только в первый раз?

У меня есть Swingworker, который мне иногда нужно отменить. Если я выполню, а затем отменю, все будет работать как положено. Если я запускаю новый экземпляр этого Swingworker, а затем пытаюсь его отменить, вызывается функция отмены, она возвращает true, но метод «doInBackground» выполняется полностью без отмены. Под полным я подразумеваю, что цикл while в функции, которую выполняет поток Swingworker, завершается (который я могу отменить только в первый раз).

Дайте мне знать, если я прояснил свою проблему, это такое странное поведение, что я просто не могу понять.

Вот мой код:

protected void firePlayButtonPlotWorker() {
    /*Cancel any previous plotWorker threads that may be running. The user might click the play
     * button again, so we ignore that if the thread isn't finished.*/
    if(plotWorker != null && !plotWorker.isDone())
    {
        System.err.println("Cancelling plot thread");
        plotWorker.cancel(true);
    }


    /*Create a SwingWorker so that the computation is not done on the Event Dispatch Thread*/
    plotWorker = new SwingWorker<Void, Void>() 
    {
        @Override
        public Void doInBackground() 
        {

            System.err.println("Plot Swing Worker Thread starting");
            playAudio(sceneManager.getScenes()); //Computation that requires an asynchronous while loop
            System.err.println("Plot Swing Worker Thread ended");
            return null;
        }

        @Override
        public void done() 
        {
            plotWorker = null;
        }
    };


    plotWorker.execute();
}

public void handleAudioEvent(AudioState audioState)
{
    switch (audioState)
    {
    case PLAY:
        firePlayButtonPlotWorker();
        break;
    case PAUSE:
        if(plotWorker != null)
        {
            boolean cancelBool = plotWorker.cancel(true);
            System.out.println("Cancelled? " + cancelBool);
        }
        break;
    case STOP:
        if(plotWorker != null)
        {
            plotWorker.cancel(true);
        }
        audioPlayerMarkerBean.setMarkerLocation(0);
        double[] coord = {0.0, 0.0};
        marker.drawMarker(coord);
        break;
    }
}

person smuggledPancakes    schedule 25.02.2011    source источник
comment
Я думаю, ключевая проблема, которую мы еще не знаем, заключается в том, что именно здесь происходит: playAudio(sceneManager.getScenes()); Как ваша отмена SwingWorker должна остановить выполнение этого метода? Ваш цикл while проверяет логическое значение и останавливается?   -  person Hovercraft Full Of Eels    schedule 26.02.2011
comment
Я согласен. Swing worker выглядит правильно установленным, выполненным и отмененным, поэтому ключевым кодом является сама фоновая задача. Не зная, как и если вы проверяете отмены или разрешаете прерывания, пытаться диагностировать проблему будет чистой догадкой.   -  person gcooney    schedule 26.02.2011


Ответы (1)


Вызов отмены с аргументом true прервет поток, используя метод Thread.interrupt.

Поэтому, если ваш поток ожидает, спит или присоединяется, будет выдано InterruptedException. В противном случае будет установлен статус прерывания потока.

Если вы проглотите InterruptedException, поток будет продолжаться до конца. Если поток работает (т. е. не ожидает, не спит или не присоединяется), когда он прерван, он также продолжит работу. Вы должны регулярно проверять статус прерывания потока (используя Thread.currentThread.isInterrupted()) в своей фоновой задаче и прекращать выполнение, как только он возвращает значение true.

person JB Nizet    schedule 25.02.2011
comment
Спасибо за информацию. Я наивно полагал, что вызов отмены в моем потоке отменит работу, которую он выполнял. Теперь я вижу, что мне нужно не только отменить свой поток, но и проверить состояние потока в коде, выполняемом этим потоком, и вручную остановить его, когда поток будет отменен. Если то, что я только что написал, неверно, дайте мне знать. Теперь я получаю ожидаемое поведение в своей программе. - person smuggledPancakes; 28.02.2011