以线程安全的方式访问EclipsePreferences(Project)

时间:2015-09-15 19:02:58

标签: java eclipse multithreading eclipse-plugin eclipse-rcp

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

  • org.osgi.service.prefs.BackingStoreException
  • java.io.FileNotFoundException
  • org.eclipse.core.runtime.CoreException

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

使用IProject.exists()isAccessible()之类的检查进行修复的初步尝试,甚至可以检查实际.prefs文件的存在,这与预期一样无效:他们只会减少异常,但不会真正阻止它们。

所以我的问题是:您如何安全地访问ProjectScope.getNode()之类的内容?您是否需要将每次阅读放到WorkspaceJob或是否有其他一些聪明的方法可以防止上述问题,例如将读取权限放入Display.asyncExec()

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

1 个答案:

答案 0 :(得分:1)

通常scheduling rules用于同时访问工作区中的资源。

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

例如:

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