为Eclipse RCP应用程序添加Shutdown Hook的正确方法是什么?

时间:2023-01-19 23:30:35

I have an RCP application that uses a connection to a in-memory database. There is one circumstance that, when shutting down windows, the application is killed without giving it a chance to close the connection to the database.

我有一个RCP应用程序,它使用与内存数据库的连接。有一种情况是,当关闭窗口时,应用程序将被终止而不会让它有机会关闭与数据库的连接。

I researched a little and it seems that adding a Shutdown hook is the best way to detect this event and do cleanup in a Java application. However, what is the correct way to do process this if you have an RCP application, possibly with multiple editors open?

我研究了一下,似乎添加Shutdown钩子是检测此事件并在Java应用程序中进行清理的最佳方法。但是,如果您有一个RCP应用程序,可能需要打开多个编辑器,那么处理此问题的正确方法是什么?

3 个解决方案

#1


5  

Note: this blog entry suggests the following implementation for the shutdown hook:

注意:此博客条目建议关闭挂钩的以下实现:

The shutdown code must be run in the UI thread and should not be run if the workbench is being closed by other means. All dirty editors are automatically saved. This avoids prompting the user who is probably at home sleeping when their computer is shutdown. Finally the workbench is closed.

关闭代码必须在UI线程中运行,如果通过其他方式关闭工作台,则不应运行关闭代码。所有脏编辑器都会自动保存。这样可以避免在计算机关闭时提示可能在家中睡觉的用户。最后,工作台已关闭。

(so not exactly your scenario, but the implementation is still interesting in that it shows how to run it within the UI thread)

(所以不完全是你的场景,但实现仍然很有趣,因为它显示了如何在UI线程中运行它)

private class ShutdownHook extends Thread {
  @Override
  public void run() {
    try {
      final IWorkbench workbench = PlatformUI.getWorkbench();
      final Display display = PlatformUI.getWorkbench()
                                        .getDisplay();
      if (workbench != null && !workbench.isClosing()) {
        display.syncExec(new Runnable() {
          public void run() {
            IWorkbenchWindow [] workbenchWindows = 
                            workbench.getWorkbenchWindows();
            for(int i = 0;i < workbenchWindows.length;i++) {
              IWorkbenchWindow workbenchWindow =
                                        workbenchWindows[i];
              if (workbenchWindow == null) {
                // SIGTERM shutdown code must access
                // workbench using UI thread!!
              } else {
                IWorkbenchPage[] pages = workbenchWindow
                                           .getPages();
                for (int j = 0; j < pages.length; j++) {
                  IEditorPart[] dirtyEditors = pages[j]
                                           .getDirtyEditors();
                  for (int k = 0; k < dirtyEditors.length; k++) {
                    dirtyEditors[k]
                             .doSave(new NullProgressMonitor());
                  }
                }
              }
            }
          }
        });
        display.syncExec(new Runnable() {
          public void run() {
            workbench.close();
          }
        });
      }
    } catch (IllegalStateException e) {
      // ignore
    }
  }
}

It is set, as you said, in the IApplication:

如你所说,它在IApplication中设置:

public class IPEApplication implements IApplication {
  public Object start(IApplicationContext context) throws Exception {
    final Display display = PlatformUI.createDisplay();
    Runtime.getRuntime().addShutdownHook(new ShutdownHook());  }
    // start workbench...
  }
}

#2


3  

You should override the preShutdown method on your class that extends WorkbenachAdvisor. Return false to halt the shutdown process or true to continue.

您应该覆盖扩展WorkbenachAdvisor的类的preShutdown方法。返回false以停止关闭进程,或返回true以继续。

#3


1  

I tried the following code, that I execute from my IApplication implementor start() method, before the RCP application is actually launched:

我尝试了以下代码,我在实际启动RCP应用程序之前从IApplication implementsor start()方法执行:

Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
        if (PlatformUI.isWorkbenchRunning()) {
            PlatformUI.getWorkbench().close();
        }
        logger.info("Shutdown request received");
        cleanup();
    }
});

Where cleanup() closes the connection to the database. Close should ask the users to save if there is any documents open.

cleanup()关闭与数据库的连接。如果有任何文档打开,关闭应该要求用户保存。

#1


5  

Note: this blog entry suggests the following implementation for the shutdown hook:

注意:此博客条目建议关闭挂钩的以下实现:

The shutdown code must be run in the UI thread and should not be run if the workbench is being closed by other means. All dirty editors are automatically saved. This avoids prompting the user who is probably at home sleeping when their computer is shutdown. Finally the workbench is closed.

关闭代码必须在UI线程中运行,如果通过其他方式关闭工作台,则不应运行关闭代码。所有脏编辑器都会自动保存。这样可以避免在计算机关闭时提示可能在家中睡觉的用户。最后,工作台已关闭。

(so not exactly your scenario, but the implementation is still interesting in that it shows how to run it within the UI thread)

(所以不完全是你的场景,但实现仍然很有趣,因为它显示了如何在UI线程中运行它)

private class ShutdownHook extends Thread {
  @Override
  public void run() {
    try {
      final IWorkbench workbench = PlatformUI.getWorkbench();
      final Display display = PlatformUI.getWorkbench()
                                        .getDisplay();
      if (workbench != null && !workbench.isClosing()) {
        display.syncExec(new Runnable() {
          public void run() {
            IWorkbenchWindow [] workbenchWindows = 
                            workbench.getWorkbenchWindows();
            for(int i = 0;i < workbenchWindows.length;i++) {
              IWorkbenchWindow workbenchWindow =
                                        workbenchWindows[i];
              if (workbenchWindow == null) {
                // SIGTERM shutdown code must access
                // workbench using UI thread!!
              } else {
                IWorkbenchPage[] pages = workbenchWindow
                                           .getPages();
                for (int j = 0; j < pages.length; j++) {
                  IEditorPart[] dirtyEditors = pages[j]
                                           .getDirtyEditors();
                  for (int k = 0; k < dirtyEditors.length; k++) {
                    dirtyEditors[k]
                             .doSave(new NullProgressMonitor());
                  }
                }
              }
            }
          }
        });
        display.syncExec(new Runnable() {
          public void run() {
            workbench.close();
          }
        });
      }
    } catch (IllegalStateException e) {
      // ignore
    }
  }
}

It is set, as you said, in the IApplication:

如你所说,它在IApplication中设置:

public class IPEApplication implements IApplication {
  public Object start(IApplicationContext context) throws Exception {
    final Display display = PlatformUI.createDisplay();
    Runtime.getRuntime().addShutdownHook(new ShutdownHook());  }
    // start workbench...
  }
}

#2


3  

You should override the preShutdown method on your class that extends WorkbenachAdvisor. Return false to halt the shutdown process or true to continue.

您应该覆盖扩展WorkbenachAdvisor的类的preShutdown方法。返回false以停止关闭进程,或返回true以继续。

#3


1  

I tried the following code, that I execute from my IApplication implementor start() method, before the RCP application is actually launched:

我尝试了以下代码,我在实际启动RCP应用程序之前从IApplication implementsor start()方法执行:

Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
        if (PlatformUI.isWorkbenchRunning()) {
            PlatformUI.getWorkbench().close();
        }
        logger.info("Shutdown request received");
        cleanup();
    }
});

Where cleanup() closes the connection to the database. Close should ask the users to save if there is any documents open.

cleanup()关闭与数据库的连接。如果有任何文档打开,关闭应该要求用户保存。