【问题标题】:Invoke function on main thread from background thread从后台线程调用主线程上的函数
【发布时间】:2011-10-24 10:41:43
【问题描述】:

更新

我已更新此问题以包含 Java 实现的源代码,使用建议的 SwingWorker 类,以实现与 Objective-C 示例相同的结果。希望这对未来的冒险者有所帮助。

Document myDoc = ...;
Model myModel = ...;

SwingWorker analyzeDocument = new SwingWorker<Dictionary, Void>() {
    @Override
    public Dictionary doInBackground() {
        return myDoc.analyze();
    }

    @Override
    public void done() {
        try {
            stats = get();
            myModel.setDict(stats);
            myModel.setNeedsDisplay(true);
        } catch(InterruptedException ex) {
            // log
        } catch(ExecutionException ex) {
            // log
        }
    }
};

analyzeDocument.execute();

原帖

我在并发编程方面缺乏经验,我希望有人可以向我解释如何实现这一点。

在 Objective-C(使用 GCD)中,您可以执行以下操作:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
     NSDictionary *stats = [myDoc analyze];
     dispatch_async(dispatch_get_main_queue(), ^{
       [myModel setDict:stats];
       [myStatsView setNeedsDisplay:YES];
       [stats release];
     });
 });

这段代码将在后台线程中执行[myDoc analyze],并在一个回调函数之后更新将在主线程中执行的UI。换句话说,后台线程向主线程发送一个中断,将匿名函数加入到主线程的待调用队列中。显然我不能在 Java 中使用匿名函数,但这不是重点。

我有兴趣在 Java 中为此做一些事情。我有一个Runnable 对象,它在文件系统中执行一堆东西。完成后,我想相应地更新 UI。

为了在执行此操作时不挂起主线程(即:backgroundThread.join();),我已将后台线程设置为执行回调函数以更新 UI。但这不是一个好主意,我不希望非 GUI 线程更新 GUI。

我想到的其他一些想法是轮询,但这似乎将周期抛到了窗外。根据同样的判断,使用 Futures 似乎也不是答案。这一切似乎都违背了异步操作的目的。

我唯一能想到的另一件事是使用后台线程中的SwingUtilities.invokeLater 并使用它来更新GUI。但我很好奇这将在哪个线程中执行。

也许我的看法只是扭曲了,但这似乎是一个相当大的部分要忽略。我只是想以错误的方式解决这个问题吗?

【问题讨论】:

    标签: java swing concurrency swingworker runnable


    【解决方案1】:

    您是否考虑过创建和使用SwingWorker 对象?这使您可以轻松地在事件线程的线程后台运行代码,实际上也是一个 Future 对象,因此它可以返回结果,您可以在其done() 方法中使用此结果来更新 GUI事件线程。您甚至可以通过 publish/process 方法对在运行过程中调用 Swing 事件线程。

    有关更多信息,请查看:Concurrency in Swing

    【讨论】:

    • 是的,这就是我要找的。非常感谢。
    • @IanBishop:不,谢谢!你的投票给了我 1000 分的 Java,给了我一个 Java 金徽章! :)
    • @Hovercraft,恭喜你,当之无愧! :D
    【解决方案2】:

    如果您使用Callable&lt;V&gt; 而不是Runnable,则可以返回一个值。

    另外,看看Executors的课程。

    【讨论】:

    猜你喜欢
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多