6

我正在尝试SwingWorker在我的应用程序中实现一个类。有没有办法设置SwingWorker“超时”的时间长度?我在想也许会抛出一个OutOfTime我可以捕获然后处理的异常。我只是不确定如何实现它。

感谢你的帮助!

4

4 回答 4

4

为什么不将您的任务嵌入到 Runnable 中,将其放入新的单线程ExecutorService中,然后get()对生成的Future执行适当的超时。这将为您提供超时功能,因为get()如果作业未及时完成,则会引发异常。

于 2010-03-01T15:08:00.780 回答
1

简短的回答是“这很难”,具体取决于您的要求。我强烈推荐阅读Java Concurrency In Practice

您可以做的基本事情是(a)确保您的 SwingWorker 的 Runnable 是中断友好的,并且(b)设置一个 Timer(或使用 Brian 提到的阻塞 get() 调用)来取消您的 Future。

于 2010-03-01T15:18:46.417 回答
1

内部类 MySwingWorker 可能会满足您的需要:

package com.misc;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class FutureStuffGUI extends JFrame {
/**
 * Provides a variant of SwingWorker which operates with a timeout.
 * 
 * @param <T>
 */
private static abstract class MySwingWorker<T> {

    private T result;
    private Exception raised;

    /**
     * Constructor.
     * 
     * @param timeout
     * @param timeUnit
     */
    public MySwingWorker(final long timeout, final TimeUnit timeUnit) {
        result = null;
        raised = null;

        System.out.println(Thread.currentThread().getName() + " starting");
        final FutureTask<T> future = new FutureTask<T>(new Callable<T>() {
            public T call() throws Exception {
                System.out.println(Thread.currentThread().getName() + " running");
                T result = doInBackground();
                return result;
            }
        });
        System.out.println(Thread.currentThread().getName() + " future: " + future);
        final Thread runner = new Thread(null, future, "FutureThread");
        Thread watcher = new Thread(null, new Runnable() {

            @Override
            public void run() {
                runner.start();
                try {
                    result = future.get(timeout, timeUnit);
                } catch (Exception ex) {
                    raised = ex;
                }
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        assert SwingUtilities.isEventDispatchThread();
                        done();
                    }
                });
            }
        }, "WatcherThread");
        watcher.start();
    }

    /**
     * Implement this method as the long-running background task.
     * 
     * @return
     * @throws Exception
     */
    abstract protected T doInBackground() throws Exception;

    /**
     * This method is invoked from the UI Event Dispatch Thread on completion or timeout.
     */
    abstract protected void done();

    /**
     * This method should be invoked by the implementation of done() to retrieve
     * the result.
     * 
     * @return
     * @throws Exception
     */
    protected T get() throws Exception {
        assert SwingUtilities.isEventDispatchThread();
        if (raised != null) {
            throw raised;
        } else {
            return result;
        }
    }
}

public FutureStuffGUI() {
    super("Hello");
    init_components();
}

private void init_components() {
    JPanel panel = new JPanel();
    JButton button = new JButton("Press");
    panel.add(button);
    add(panel);
    pack();

    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            new MySwingWorker<String>(5, TimeUnit.SECONDS) {

                @Override
                protected String doInBackground() throws InterruptedException {
                    assert !SwingUtilities.isEventDispatchThread();
                    System.out.println(Thread.currentThread().getName() + " doInBackground");
//                        if (true) { throw new RuntimeException("Blow up"); }
                    Thread.sleep(6 * 1000);
                    return "Hello world!";
                }

                @Override
                protected void done() {
                    assert SwingUtilities.isEventDispatchThread();
                    String result;
                    try {
                        result = get();
                        System.out.println(Thread.currentThread().getName() + " done; result: " + result);
                    } catch (Exception ex) {
                        System.out.println(Thread.currentThread().getName() + " done; errored:");
                        ex.printStackTrace();
                    }
                }
            };
        };
    });
}

public static void main(String[] args) {
    FutureStuffGUI ui = new FutureStuffGUI();
    ui.setVisible(true);
}

}

于 2010-08-06T14:23:59.763 回答
0

不使用 SwingWorker 的任何特殊原因。获取(长,java.util.concurrent.TimeUnit)?它将抛出 TimeoutException,您可以在应用程序中轻松处理。

于 2012-11-05T11:35:00.763 回答