2014-10-21 6 views
0

처음으로 빈 작업 영역에서 실행하면 Java 프로젝트 작성을 위해 마법사에서 작업하고 잘못된 스레드 액세스 예외가 발생합니다. 나는 JavaProjectWizard 유사 나의 마법사를 구현하기 위해 노력하지만, 나는 두 번째 페이지를 필요로하지 않는, 그래서 첫 번째 페이지에서 마무리를 수행하고 사전에 두 번째 페이지를 초기화하려고 :SWTException : 잘못된 스레드 액세스

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.

해당 IRunnableWithProgressforked으로 실행되기 때문에이 문제의 근본 원인은 잘못된 스레드에서 ImageDescriptorRegistry이 생성 된 것으로 보입니다. 하지만 왜 정상적으로 작동합니까? JavaProjectWizard? 그리고 주된 질문은 그것이 나의 마법사를 위해 어떻게 작동하게 하는가입니다.

답변

1

Display.checkDevice에는 버그가 없습니다.

NewJavaProjectWizardPageTwo.performFinish에 대한 전화가 백그라운드 스레드에서 실행 중이지만 사용자 인터페이스 스레드에서 초기화해야하는 코드는 ImageDescriptorRegistry입니다.

가끔씩 다른 작업이 레지스트리를 초기화했을 수 있기 때문에 간헐적입니다.

+0

이유 및 불규칙성에 대한 설명이 좋습니다. –

+0

경고/오류 아이콘을로드하는'setErrorMessage (message)'와'setMessage (message, DialogPage.WARNING) '메소드를 사용합니다. 내 읽기 이것이 문제의 근원이다. –

+0

하지만 설명 할 수없는 것은 원래 Eclipse 마법사가 오류 아이콘을로드하고 마무리 작업을 분기하고 예외를 throw하지 않는다는 것입니다. –

2

getContainer().run(true, true, runnable);은 실행 가능한 스레드를 별도의 스레드에서 실행합니다. 따라서 첫 번째 매개 변수 fork이 발생합니다. javaWizardPageTwo.performFinish()을 호출하면 UI 스레드에 액세스하려고 시도하고 잘못된 스레드 액세스 예외가 발생합니다.

fork 매개 변수를 false로 설정하면 코드가 현재 스레드에서 실행됩니다.

javaWizardPageTwo.performFinish()으로 직접 전화하지 않으시겠습니까?

+0

원래 JavaProject Wizard를 기반으로 코드를 만들었습니다. 해당 부분은 [NewElementWizard] (http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/4.3/org.eclipse.jdt/ui/3.9.0/org/eclipse/jdt)에 있습니다. /internal/ui/wizards/NewElementWizard.java#NewElementWizard.performFinish%28%29). 'getContainer(). run (canRunForked(), true, runnable); 그리고'canRunForked()'는 항상 참을 리턴합니다. –

+0

'javaWizardPageTwo '를 호출하면된다.performFinish()'직접'IProgressMonitor'를 사용할 수 없었습니다. –

+0

Eclipse forkes 스레드가 실제로 도움이되는 방법에 대한 힌트가 있습니다. 다음 답변에 계속 추가 정보를 제공해 주시면 정말 대단합니다 !!! –