SecondaryLoop.enter()在EDT上调用exit()之前不会阻塞

问题描述 投票:3回答:1

摘要

由于某种原因,当我在AWT事件调度线程(EDT)上调用SecondaryLoop.enter()时,它不等待SecondaryLoop.enter()被调用才解除阻塞。

由于我认为SecondaryLoop.exit()不是一个非常知名的类,所以我会做一个简短的概述:

[通常,在EDT上运行任何长时间执行或阻止的代码是一个坏主意,因为这样,在该代码终止之前,您的应用将无法响应任何事件。 SecondaryLoop.exit()允许您创建一个新的事件循环,该循环将处理事件,从而使您可以阻止EDT而不会失去响应能力。这是摆动模式对话框用来允许您在等待对话框关闭时阻止EDT的功能,但仍然允许对话框本身上的控件能够操作。

[创建了SecondaryLoop实例后,您应该可以调用EventQueue.createSecondaryLoop(),并且它应该阻塞直到调用SecondaryLoop

来自文档

此方法可以由包括事件分发线程在内的任何线程调用。该线程将被阻塞,直到调用exit()方法或终止循环为止。在任何一种情况下,都会在事件分发线程上创建一个新的辅助循环以分发事件。

不过,我并不完全确定当它说“或循环终止”时的含义。那可能是我的问题。

测试代码

在EDT以外的线程上调用enter()方法,正如我期望的那样阻塞:

exit()

输出:

enter()

但是,如果在EDT上调用它,它会阻塞大约一秒钟,然后继续:

System.out.println("Enter Loop"); Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop().enter(); System.out.println("Done (we should never get here)");

输出:

Enter Loop

根据tevemadar的评论(感谢BTW),我已经更新了代码,以防止发生任何可能的垃圾回收问题:

System.out.println("Enter Loop"); try { SwingUtilities.invokeAndWait(() -> Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop().enter()); } catch (InvocationTargetException | InterruptedException e) { e.printStackTrace(); } System.out.println("Done (we should never get here)");

输出:

Enter Loop Done (we should never get here)

因此,尽管这是一个很好的建议,但这似乎不是我的问题。

这似乎与文档(以及//Storing loop in array as a quick hack to get past the // "final or effectively final" issue when using this in the invokeAndWait SecondaryLoop loop[] = new SecondaryLoop[1]; System.out.println("Enter Loop"); try { SwingUtilities.invokeAndWait(() -> { loop[0] = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop(); loop[0].enter(); }); } catch (InvocationTargetException | InterruptedException e) { e.printStackTrace(); } System.out.println("Done (we should never get here)"); //Just printing this to make sure that it is used after the invokeAndWait is done. This is just //to make sure there isn't some sort of optimization thing that is deciding that we don't //need this anymore and allowing the loop to be garbage collected System.out.println(loop[0]); 的整个目的对我来说是矛盾的。我缺少什么吗?

环境

OS:Windows 10

Java:

Enter Loop Done (we should never get here) java.awt.WaitDispatchSupport@2401f4c3

更新

直觉上,我尝试添加一个计时器,该计时器向EDT循环不断添加更多事件。似乎添加计时器使循环保持活动并使其阻塞:

SecondaryLoop

使用该代码,它会按我期望的那样挂起,并且如果我在一段时间后放入一些在循环中调用C:\Program Files\Java\jre8\bin>java.exe -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
方法的代码,它会按照我的预期终止。因此,似乎循环必须在没有事件的情况下经过一定时间才能终止自身(但仅当它最初是出于某种原因从EDT触发...)。

我想我可以添加计时器,每当我需要使用此功能时,它什么都不做,但是我认为这绝对是解决方法,而不是修复。

总结由于某种原因,当我在AWT事件调度线程(EDT)上调用SecondaryLoop.enter()时,它不会等待取消阻塞之前等待SecondaryLoop.exit()的调用。背景由于我认为...

java event-dispatch-thread
1个回答
0
投票
解决了这个问题(至少这个特定的问题,我还有更多相关的问题,但是我希望我能自己解决这些问题。]]

我决定开始在Java源代码中进行调试,并且我意识到由于//Add a keep alive timer which adds an event to the EDT for every 0.5 sec new Timer(500, null).start(); System.out.println("Enter Loop"); try { SwingUtilities.invokeAndWait(() -> Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop().enter()); } catch (InvocationTargetException | InterruptedException e) { e.printStackTrace(); } System.out.println("Done (we should never get here)"); 中的这一段,我的线程被释放了。

exit()

© www.soinside.com 2019 - 2024. All rights reserved.