SWT、多线程和异常
SWT, multiple threads, and exceptions
我在主 GUI 程序中使用 SWT。在其中,我为 运行 一些程序创建了另一个线程。但是,如果在这些过程中遇到一些错误,我想通过显示一个消息框来向用户报告。因为在 SWT 中,只有一个线程可以执行 GUI 操作,我让程序 运行ner 抛出异常,因此 GUI 线程可以处理它们。但是,我遇到了问题,因为我为程序 运行ner 创建了一个新线程(为了不占用 GUI 线程,它会不断更新和刷新一些图形),但结果是,异常发生的事情被卡在该线程的一部分,无法创建错误消息框。关于如何处理这个问题有什么建议吗?
private void goButtonActionPerformed()
{
// create the program runner object
ProgramRunner PR = new ProgramRunner(); // real code passes in data to be used
try{
// check all necessary parameters are entered
boolean paramsOK = PR.checkParams();
if (paramsOK)
{
// all necessary information is available. Start Processing.
Thread t = new Thread() {
public void run()
{
try{
PR.runPrograms();
}
catch (IOException iox)
{
// This does not work to catch & display the exceptions
// which took place in PR.runPrograms(), because this
// thread is not allowed to perform GUI operations.
// However, I don't know how to pass this
// exception / error notification out of this thread.
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
}
};
t.start();
}
}
catch (IOException iox)
{
// this works to catch & display the exceptions which took place
// in PR.checkParams() because that is not a separate thread
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
在 Display.getDefault().asyncExec 中包装捕获逻辑以在 UI 线程上显示错误消息:
Thread t = new Thread()
{
public void run()
{
try
{
PR.runProgram();
}
catch ( final IOException iox )
{
Display.getDefault().asyncExec( new Runnable()
{
public void run()
{
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
});
}
}
});
t.start();
然后可以在UI线程中显示异常。
您需要在 UI 线程中安排 UI 代码 运行。您可以使用 Display
的 asyncExec
或 syncExec
方法来执行此操作。
syncExec
暂停当前线程,直到 UI 代码已 运行。 asyncExec
不会挂起线程,运行 会尽快执行 UI 代码。
您可以使用 Display.getDefault()
在任何线程中获取当前显示,因此您可以执行以下操作:
Display.getDefault().asyncExec(() ->
{
if (m_Shell != null && !m_Shell.isDisposed()) {
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
});
我在这里为 Runnable
使用了 Java 8 lambda 表达式,因为它比传统方法更短。
由于此代码是 运行 异步执行的,因此最好检查 shell 是否不为 null 且未被处置。
我在主 GUI 程序中使用 SWT。在其中,我为 运行 一些程序创建了另一个线程。但是,如果在这些过程中遇到一些错误,我想通过显示一个消息框来向用户报告。因为在 SWT 中,只有一个线程可以执行 GUI 操作,我让程序 运行ner 抛出异常,因此 GUI 线程可以处理它们。但是,我遇到了问题,因为我为程序 运行ner 创建了一个新线程(为了不占用 GUI 线程,它会不断更新和刷新一些图形),但结果是,异常发生的事情被卡在该线程的一部分,无法创建错误消息框。关于如何处理这个问题有什么建议吗?
private void goButtonActionPerformed()
{
// create the program runner object
ProgramRunner PR = new ProgramRunner(); // real code passes in data to be used
try{
// check all necessary parameters are entered
boolean paramsOK = PR.checkParams();
if (paramsOK)
{
// all necessary information is available. Start Processing.
Thread t = new Thread() {
public void run()
{
try{
PR.runPrograms();
}
catch (IOException iox)
{
// This does not work to catch & display the exceptions
// which took place in PR.runPrograms(), because this
// thread is not allowed to perform GUI operations.
// However, I don't know how to pass this
// exception / error notification out of this thread.
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
}
};
t.start();
}
}
catch (IOException iox)
{
// this works to catch & display the exceptions which took place
// in PR.checkParams() because that is not a separate thread
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
在 Display.getDefault().asyncExec 中包装捕获逻辑以在 UI 线程上显示错误消息:
Thread t = new Thread()
{
public void run()
{
try
{
PR.runProgram();
}
catch ( final IOException iox )
{
Display.getDefault().asyncExec( new Runnable()
{
public void run()
{
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
});
}
}
});
t.start();
然后可以在UI线程中显示异常。
您需要在 UI 线程中安排 UI 代码 运行。您可以使用 Display
的 asyncExec
或 syncExec
方法来执行此操作。
syncExec
暂停当前线程,直到 UI 代码已 运行。 asyncExec
不会挂起线程,运行 会尽快执行 UI 代码。
您可以使用 Display.getDefault()
在任何线程中获取当前显示,因此您可以执行以下操作:
Display.getDefault().asyncExec(() ->
{
if (m_Shell != null && !m_Shell.isDisposed()) {
MessageBox mb = new MessageBox(m_Shell, SWT.ICON_ERROR);
mb.setMessage(iox.getMessage());
mb.open();
}
});
我在这里为 Runnable
使用了 Java 8 lambda 表达式,因为它比传统方法更短。
由于此代码是 运行 异步执行的,因此最好检查 shell 是否不为 null 且未被处置。