访问 EclipsePreferences 的线程安全方式(项目)

Thread-Safe way to access EclipsePreferences (Project)

我目前正在开发一个 Eclipse-RCP 应用程序,它通过 ProjectScope 使用 EclipsePreference 机制存储每个项目的首选项。起初这似乎工作得很好,但我们 运行 在多线程场景中(读取)访问这些首选项时遇到了麻烦,同时对工作区进行了更改。似乎特别有问题的是在通过异步用户操作(右键单击项目 -> 删除项目)删除项目时访问这样的首选项节点 (ProjectScope.getNode())。在这种情况下,我们得到了

的完美组合

基本上他们都抱怨基础文件不再存在。

最初尝试使用 IProject.exists()isAccessible() 之类的检查来 修复 这个问题,甚至检查实际 .prefs 文件是否存在正如预期的那样徒劳无功:他们只是降低了例外的可能性,但并没有真正阻止它们。

所以我的问题是:您应该如何安全地访问 ProjectScope.getNode() 之类的内容?您是否需要将每次读取都放入 WorkspaceJob 中,或者是否有其他巧妙的方法来防止上述问题,例如将读取访问放入 Display.asyncExec()?

虽然我试过了,但我并没有在Eclipse文档中真正找到上述问题的答案。

通常scheduling rules用于并发访问工作空间中的资源。

我从未使用过 ProjectScopeed 首选项,但如果它们存储在项目或其元数据中,那么调度规则应该有助于协调访问。如果您 运行 在作业中设置首选项访问代码,则设置适当的调度规则应该:

例如:

IProject project = getProjectForPreferences( projectPreferences );
ISchedulingRule rule = project.getWorkspace().getRuleFactory().modifyRule( project );
Job job = new Job( "Access Project Preferences" ) {
  @Override
  protected IStatus run( IProgressMonitor monitor ) {
    if( project.exists() ) {
      // read or write project preferences
    }
    return Status.OK_STATUS;
  }
};
job.setRule( rule );
job.schedule();

代码获取修改项目的规则,只有当没有其他作业具有冲突规则运行时,作业才能保证运行。

如果您的代码不在作业中 运行,您还可以使用 IJobManager.beginRule()endRule() 手动获取锁。

例如:

ISchedulingRule rule = ...;
try {
  jobManager.beginRule( rule, monitor );
  if( project.exists() ) {
    // read or write project preferences
  }
} finally {
  jobManager.endRule( rule );
}

尽管看起来很尴尬,但对 beginRule 的调用必须 在 try 块内,有关详细信息,请参阅 JavaDoc