处理SwingWorker.doInBackground引发的异常的正确方法 [英] The proper way to handle exceptions thrown by the SwingWorker.doInBackground

查看:316
本文介绍了处理SwingWorker.doInBackground引发的异常的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

处理 doInBackground 方法/SwingWorker.html rel = nofollow noreferrer> SwingWorker 类用于调用 get 方法从< a href = http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#done() rel = nofollow noreferrer> 完成 方法,如此处此处

get 方法d表示以下内容:

The documentation for the get method states the following:


等待完成计算所需的时间,然后检索
的结果。

Waits if necessary for the computation to complete, and then retrieves its result.

注意:在 Event Dispatch Thread 上调用 get 会阻止 all
事件,包括重绘,从处理到完成
SwingWorker 完成。

Note: calling get on the Event Dispatch Thread blocks all events, including repaints, from being processed until this SwingWorker is complete.

因此,如果 get 方法导致在 done 方法内等待,则实际上由于 done 方法是在EDT上执行的,因此会阻塞事件调度线程。

Therefore, if the get method causes a waiting within the done method, in fact it would block the Event Dispatch Thread, since the done method is executed on EDT.

但是,在执行简单的操作之后测试建议的解决方案,您可能会注意到EDT没有被阻止:发生此现象的原因是在完成 get 方法c $ c>方法,因此在计算操作结果之后将调用 get ,因此对其的调用不会阻止EDT。这种动机正确吗?

However, after performing a simple test of the proposed solution, you may notice that the EDT is not blocked: this behavior occurs because the get method is invoked within the done method, so get is invoked after the result of the operation was calculated, and therefore the call to it will not block the EDT. Is this motivation correct?

推荐答案


因此,如果get方法导致在done方法中等待,实际上,它会阻塞事件调度线程,因为done方法是在EDT上执行的。

Therefore, if the get method causes a waiting within the done method, in fact it would block the Event Dispatch Thread, since the done method is executed on EDT.

实际上,如果调用了done, doInBackground 已经返回,因此在完成内调用 get 不会阻止事件调度线程。

Actually, if done is called, the doInBackground has already returned, therefore calling get within done will NOT block the Event Dispatching Thread.

如果您使用 PropertyChangeListener 支持并监视更改,情况也是如此。状态为 Done

The same goes if you are using the PropertyChangeListener support and monitoring the change in state to DONE

已更新

因此,在查看 SwingWorker在 doInBackground之前调用完成之后'已完成,这意味着对被取消的工作人员调用 get 会无意地阻止EDT,基本的解决方法是y通过检查 SwingWorker#isCancelled 状态来忽略返回结果。让我们面对现实,如果取消了工作程序,则返回结果未知/不确定,因此最好不要尝试获取它。

So, after having a look at SwingWorker calls 'done' before the 'doInBackground' is finished, which would mean that calling get on a cancelled worker would block the EDT indeventially, the basic work around is actually to ignore the return result by checking the SwingWorker#isCancelled state. Let's face it, if the worker is cancelled, the return result is unknown/undefined, so it's best NOT to try and get it.

作为一个示例(基于错误中的代码)

As an example (based on the code from the bug)

import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        SwingWorker<String, String> worker = new SwingWorker<String, String>() {
            @Override
            protected String doInBackground() throws Exception {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        System.out.println("Working...");
                        Thread.sleep(1000);

                    }
                } catch (InterruptedException ex) {
                    System.out.println("Got interrupted!");
                }

                try {
                    System.out.println("Cleaning up");
                    Thread.sleep(10000);
                    System.out.println("Done cleaning");
                } catch (InterruptedException ex) {
                    System.out.println("Got interrupted second time!");
                }

                return null;
            }

            @Override
            protected void done() {
                System.out.println("Done");
                if (!isCancelled()) {
                    long start = System.currentTimeMillis();
                    try {
                        get();
                    } catch (InterruptedException | ExecutionException ex) {
                        ex.printStackTrace();
                    }
                    long end = System.currentTimeMillis();
                    System.out.println("Took " + ((end - start) / 1000d));
                } else {
                    System.out.println("Was cancelled");
                }
            }
        };

        worker.execute();

        Thread.sleep(10000);

        worker.cancel(true);
        Thread.sleep(20000);
    }
}

这篇关于处理SwingWorker.doInBackground引发的异常的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆