由于某种原因,当我在AWT事件调度线程(EDT)上调用SecondaryLoop.enter()
时,它不等待SecondaryLoop.enter()
被调用才解除阻塞。
SecondaryLoop.exit()
不是一个非常知名的类,所以我会做一个简短的概述:[通常,在EDT上运行任何长时间执行或阻止的代码是一个坏主意,因为这样,在该代码终止之前,您的应用将无法响应任何事件。 SecondaryLoop.exit()
允许您创建一个新的事件循环,该循环将处理事件,从而使您可以阻止EDT而不会失去响应能力。这是摆动模式对话框用来允许您在等待对话框关闭时阻止EDT的功能,但仍然允许对话框本身上的控件能够操作。
[创建了SecondaryLoop
实例后,您应该可以调用EventQueue.createSecondaryLoop()
,并且它应该阻塞直到调用SecondaryLoop
。
来自文档
此方法可以由包括事件分发线程在内的任何线程调用。该线程将被阻塞,直到调用exit()方法或终止循环为止。在任何一种情况下,都会在事件分发线程上创建一个新的辅助循环以分发事件。
不过,我并不完全确定当它说“或循环终止”时的含义。那可能是我的问题。
测试代码
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源代码中进行调试,并且我意识到由于//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()