2016-03-27 8 views
1

Eclipseでウィザードで何かする必要があるので、JDTでウィザードを実装した方法をチェックして、わからないこの奇妙なコードを見つけました。Eclipse(JDT) - ウィザードのperformFinishメソッド

すでに実行中のジョブからコードが呼び出された場合(そのジョブのスケジューリングルールを使用する場合)、ウィザードのスケジューリングルール(getSchedulingRuleから返されます)は無視されます。したがって、ウィザードがワークスペース全体のスケジューリングルールを必要とするが、現在のスレッドがすでにジョブを実行している場合、代わりにこのジョブのスケジューリングルールが使用されます。これにより、新しいランナブルがワークスペースで実行されるときに問題が発生する可能性があります。私はコードにいくつかのコメントを追加しましたので、より明確です。

Eclipseのエキスパートが、tryブロックがそのまま(getSchedulingRuleを使用するだけではなく)そのまま実装されている理由を説明できますか?

NewElementWizard

/** 
    * Returns the scheduling rule for creating the element. 
    * @return returns the scheduling rule 
    */ 
    protected ISchedulingRule getSchedulingRule() { 
     return ResourcesPlugin.getWorkspace().getRoot(); // look all by default 
    } 

    /* 
    * @see Wizard#performFinish 
    */ 
    @Override 
    public boolean performFinish() { 
     IWorkspaceRunnable op= new IWorkspaceRunnable() { 
      @Override 
      public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException { 
       try { 
        finishPage(monitor); 
       } catch (InterruptedException e) { 
        throw new OperationCanceledException(e.getMessage()); 
       } 
      } 
     }; 
     try { 
     //TODO: i need explanation of this block. Wizard should be used 
     // from UI thread, so the code Job.getJobManager().currentJob() 
     // means that there is possible Job currently executed by UI thread. 
     // Ok now if there is a job, use its scheduling rule ignoring getSchedulingRule. 
     // This could be maybe to force that this new runnable isn't executed until this thread finishes 
     // its current Job. Okb but if the current Job rule isn't so powerfull as this wizard needs, what than? 
     // It will cause error when executing op, because the runnable will not have enough access 
     // cause ignoring getSchedulingRule... 
      ISchedulingRule rule= null; 
      Job job= Job.getJobManager().currentJob(); 
      if (job != null) 
       rule= job.getRule(); 
      IRunnableWithProgress runnable= null; 
      if (rule != null) 
       runnable= new WorkbenchRunnableAdapter(op, rule, true); 
      else 
       runnable= new WorkbenchRunnableAdapter(op, getSchedulingRule()); 
      getContainer().run(canRunForked(), true, runnable); 
     } catch (InvocationTargetException e) { 
      handleFinishException(getShell(), e); 
      return false; 
     } catch (InterruptedException e) { 
      return false; 
     } 
     return true; 
    } 

答えて

1

私はこのすべてを説明できるかわからないが、注意すべき重要なことは、

Job.getJobManager().currentJob(); 

だけ現在のスレッドで、現在のジョブを返すということですperformFinishは通常UIスレッドで実行されるため、これは通常のバックグラウンドジョブではありません。 UIJobジョブはUIスレッドで実行されます。このコードは、ウィザードや関連するコードがすでに開始しているUIのジョブからルールを取得しようとしているようです。コールの

true引数:

new WorkbenchRunnableAdapter(op, rule, true) 

は、スレッドが変更された場合WorkbenchRunnableAdapter

Job.getJobManager().transferRule(fRule, thread); 

を呼び出すようになります。これはコードが、実行可能ファイルの実行中に以前使用していたジョブと同じルールを使用し続けることを試みていることを意味します。

+0

現在のジョブがたとえばプロジェクトAで操作するルールを持っていて、ウィザードで作業スペース全体を操作するルールが必要な場合、コードが現在のジョブのルールを使用する場合は機能しません(ルールでは、プロジェクトAでは、ウィザードはワークスペース全体のルールを必要とします) – Krab

+0

これはUIスレッドで実行されているため、他のタスクによって起動されたUIジョブが実行を終了するまで、ウィザードは開始できません。だから私は、ウィザードによって開始されたものだけが現在の仕事になる可能性があると思う。おそらく、ウィザードは適切なルールを持つものだけを使用します。 –

+0

ああ、今私は理解していると思う、ありがとう – Krab

関連する問題