使用线程和 ProcessBuilder

发布于 2024-07-30 18:04:45 字数 414 浏览 11 评论 0原文

我真的不熟悉使用线程,所以我希望有人可以帮助我找出最好的方法来做到这一点。

我的 java 应用程序中有一个 JButton...当您单击该按钮时,我有一个进程生成器,它创建一个执行一些外部 python 代码的进程。 python 代码生成一些文件,这可能需要一些时间。 当 python 代码执行完毕后,我需要将这些文件加载​​到我的 Java 应用程序中的小程序中。

在当前的形式中,我在调用外部 python 文件的代码中有一个 p.waitFor()...因此,当您单击按钮时,按钮会挂起(实际上整个应用程序挂起),直到该过程完成。 显然,我希望用户能够在此过程进行时与应用程序的其余部分进行交互,但是一旦完成,我希望我的应用程序知道它,以便它可以将文件加载到小程序中。

做这个的最好方式是什么?

感谢您的帮助。

I am really unfamiliar with working with threads, so I was hoping someone could help me figure out the best way to do this.

I have a JButton in my java application...when you click on the button, I have a Process Builder that creates a process which executes some external python code. The python code generates some files, and this can take some time. When the python code is done executing, I need to load those files into an applet within my Java application.

In its current form, I have a p.waitFor() within the code that calls the external python file...so when you click on the button, the button hangs (the entire application hangs actually) until the process is done. Obviously, I want the user to be able to interact with the rest of the application while this process is going on, but as soon as it's done, I want my application to know about it, so that it can load the files into the applet.

What is the best way to do this?

Thanks for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

滥情空心 2024-08-06 18:04:45

您应该使用 SwingWorker 来调用 Python后台线程上的进程。 这样,您的 UI 将在长时间运行的任务运行时保持响应。

// Define Action.
Action action = new AbstractAction("Do It") {
  public void actionPerformed(ActionEvent e) {
    runBackgroundTask();
  }
}

// Install Action into JButton.
JButton btn = new JButton(action);

private void runBackgroundTask() {
  new SwingWorker<Void, Void>() {
    {
      // Disable action until task is complete to prevent concurrent tasks.
      action.setEnabled(false);
    }

    // Called on the Swing thread when background task completes.
    protected void done() {
      action.setEnabled(true);

      try {
        // No result but calling get() will propagate any exceptions onto Swing thread.
        get();
      } catch(Exception ex) {
        // Handle exception
      }
    }

    // Called on background thread
    protected Void doInBackground() throws Exception {
      // Add ProcessBuilder code here!
      return null; // No result so simply return null.
    }
  }.execute();
}

You should use SwingWorker to invoke the Python process on a background thread. This way your UI will remain responsive whilst the long-running task runs.

// Define Action.
Action action = new AbstractAction("Do It") {
  public void actionPerformed(ActionEvent e) {
    runBackgroundTask();
  }
}

// Install Action into JButton.
JButton btn = new JButton(action);

private void runBackgroundTask() {
  new SwingWorker<Void, Void>() {
    {
      // Disable action until task is complete to prevent concurrent tasks.
      action.setEnabled(false);
    }

    // Called on the Swing thread when background task completes.
    protected void done() {
      action.setEnabled(true);

      try {
        // No result but calling get() will propagate any exceptions onto Swing thread.
        get();
      } catch(Exception ex) {
        // Handle exception
      }
    }

    // Called on background thread
    protected Void doInBackground() throws Exception {
      // Add ProcessBuilder code here!
      return null; // No result so simply return null.
    }
  }.execute();
}
幽蝶幻影 2024-08-06 18:04:45

您确实想创建一个新线程来监视新进程。 正如您所发现的,仅对 UI 使用一个线程并监视子进程将使 UI 在子进程运行时看起来挂起。

这是一些示例代码,假设存在 log4j 记录器,我认为这将说明一种可能的方法......

Runtime runtime = Runtime.getRuntime();
String[] command = { "myShellCommand", "firstArgument" };

try {

    boolean done = false;
    int exitValue = 0;
    Process proc = runtime.exec(command);

    while (!done) {
        try {
            exitValue = proc.exitValue();
            done = true;
        } catch (IllegalThreadStateException e) {
            // This exception will be thrown only if the process is still running 
            // because exitValue() will not be a valid method call yet...
            logger.info("Process is still running...")
        }
    }

    if (exitValue != 0) {
        // Child process exited with non-zero exit code - do something about failure.
        logger.info("Deletion failure - exit code " + exitValue);
    }

} catch (IOException e) {
    // An exception thrown by runtime.exec() which would mean myShellCommand was not 
    // found in the path or something like that...
    logger.info("Deletion failure - error: " + e.getMessage());
}

// If no errors were caught above, the child is now finished with a zero exit code
// Move on happily

You really want to create a new thread for monitoring your new process. As you've discovered, using just one thread for both the UI and monitoring the child process will make the UI seem to hang while the child process runs.

Here's some example code that assumes the existence of a log4j logger which I think will illustrate one possible approach...

Runtime runtime = Runtime.getRuntime();
String[] command = { "myShellCommand", "firstArgument" };

try {

    boolean done = false;
    int exitValue = 0;
    Process proc = runtime.exec(command);

    while (!done) {
        try {
            exitValue = proc.exitValue();
            done = true;
        } catch (IllegalThreadStateException e) {
            // This exception will be thrown only if the process is still running 
            // because exitValue() will not be a valid method call yet...
            logger.info("Process is still running...")
        }
    }

    if (exitValue != 0) {
        // Child process exited with non-zero exit code - do something about failure.
        logger.info("Deletion failure - exit code " + exitValue);
    }

} catch (IOException e) {
    // An exception thrown by runtime.exec() which would mean myShellCommand was not 
    // found in the path or something like that...
    logger.info("Deletion failure - error: " + e.getMessage());
}

// If no errors were caught above, the child is now finished with a zero exit code
// Move on happily
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文