Reputation: 457
I'm looking to force-close a Java window even if a function is currently running - is there a way to do this? I have some functions that take quite a while in certain conditions (eg. running from a CD or another non-local location) and I want to be able to force-stop those functions and completely exit the program. Is this possible? And how can I go about doing it?
My code for exiting is below:
this.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
if (closeApplication()) {
System.exit(0);
}
}
});
And the closeApplication() function:
private boolean closeApplication() {
final JFrame temp = this;
int exitDialogResult = JOptionPane.showConfirmDialog(temp,
"Are you sure you want to exit?", "Really Closing?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (exitDialogResult == JOptionPane.YES_OPTION) {
//code here to stop various processes
return true;
}
else {
return false;
}
}
Quick edit to clarify: when my program is executing a long-running function and I attempt to close the window, the window listener doesn't even register the click.
Upvotes: 0
Views: 1590
Reputation: 4620
It seems like you are executing your long-running operations in the event dispatch thread. This is the thread which is used by the GUI to trigger all events. Thus, if you block this thread, your GUI is blocked. The close operation of a JFrame
is one of these operations. This is the reason why it is not triggered while a long-running operation is executed in the GUI thread.
To fix this, you should think about what the long-running operation is doing. In any case, you should move it to a background thread:
Does it execute an operation which can be canceled at any time, without bad things happening? In this case, you can put the operation in a daemon thread. This tells the JVM, that this thread can be terminated at any time. It should not keep the JVM alive. An example for this is an operation which requests information from a web API.
else If bad things happen when you terminate the long-running operation at any point, then you should put the operation in a non-daemon thread. In this case, it is also a bad idea to use System.exit
to shutdown your application, since this will also just kill the non-daemon threads. You need to implement a mechanism which terminates the background thread gracefully, or waits for it to finish. This can sometimes be difficult, but it is necessary. An example for this type of long-running operation is to write to a file: If you just terminate this operation, then the file will be corrupted.
See also What is Daemon thread in Java?
If you want to use an ExecutorService
for your long-running operations, then you might be interested in the method ExecutorService::shutdown
:
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
Upvotes: 1
Reputation: 14806
The problem you are facing is obvious: Your applications is getting "frozen" during long running background task because it executes on event dispatch thread. Use SwingWorker. That way, your GUI will remain responsive while your long running task runs on background thread. You could use System.exit()
for termination, but safest way would be to wait until your long running task is done.
Upvotes: 3