我在创建java项目时使用向导,如果我第一次在空工作区中运行它,则会获得无效的线程访问异常。我尝试实现类似于JavaProjectWizard
的向导,但我不需要第二页,因此我尝试从第一页执行完成并提前初始化第二页:
import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
public class SomeNewWizard
extends Wizard
implements INewWizard {
private SomeWizardPageTwo javaWizardPageTwo;
@Override
public void addPages() {
if (javaWizardPageTwo == null)
someWizardPageTwo = new SomeWizardPageTwo(newSeeAppWizardPageOne);
}
@Override
public boolean performFinish() {
/*line 109*/someWizardPageTwo .createProvisonalProject();
final IWorkspaceRunnable op = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor)
throws CoreException, OperationCanceledException {
try {
someWizardPageTwo.performFinish(new SubProgressMonitor(monitor, 1));
}
catch (InterruptedException e) {
throw new OperationCanceledException(e.getMessage());
}
finally {
monitor.done();
}
}
};
try {
rule = null;
Job job = Job.getJobManager().currentJob();
if (job != null)
rule = job.getRule();
IRunnableWithProgress runnable = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
JavaCore.run(op, rule, monitor);
}
catch (OperationCanceledException e) {
throw new InterruptedException(e.getMessage());
}
catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
getContainer().run(true, true, runnable);
}
catch (InvocationTargetException e) {
handleFinishException(getShell(), e);
return false;
}
catch (InterruptedException e) {
return false;
}
return true;
}
public class SomeWizardPageTwo
extends NewJavaProjectWizardPageTwo
{
private NewJavaProjectWizardPageOne mainPage;
public SomeWizardPageTwo(NewJavaProjectWizardPageOne mainPage)
{
super(mainPage);
this.mainPage = mainPage;
}
@Override
public IProject createProvisonalProject()
{
return super.createProvisonalProject();
}
@Override
protected IWizardContainer getContainer()
{
if (mainPage == null)
return null;
return mainPage.getWizard().getContainer();
}
}
可以找到堆栈跟踪here。
问题的根源似乎是ImageDescriptorRegistry
是从错误的线程创建的,因为相应的IRunnableWithProgress
运行forked。但我想知道为什么它适用于正常的JavaProjectWizard
呢?主要问题是:如何使它适用于我的向导?
答案 0 :(得分:2)
getContainer().run(true, true, runnable);
导致runnable在单独的线程中执行。因此,第一个参数fork
是负责任的。
对javaWizardPageTwo.performFinish()
的调用尝试访问UI线程并导致无效线程访问异常。
如果将fork
参数设置为false,则代码将在当前线程上执行。
为什么不直接致电javaWizardPageTwo.performFinish()
?
答案 1 :(得分:1)
Display.checkDevice
中没有错误。
您对NewJavaProjectWizardPageTwo.performFinish
的调用正在后台线程中运行,但代码正在使用ImageDescriptorRegistry
,需要在用户界面线程上初始化。
这是间歇性的,因为有时您做的其他事情已经初始化了注册表。