Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "E4/EAS/Progress Service"

< E4‎ | EAS
(Eclipse 3.x API)
(Eclipse 3.x API)
Line 30: Line 30:
 
* Likewise, we need a way to ensure that the runnables can be run in different runnable contexts (ie, a user job) with progress monitors and error reporting that is appropriate for where they are triggered.  See [https://bugs.eclipse.org/bugs/show_bug.cgi?id=293098 Bug 293098].
 
* Likewise, we need a way to ensure that the runnables can be run in different runnable contexts (ie, a user job) with progress monitors and error reporting that is appropriate for where they are triggered.  See [https://bugs.eclipse.org/bugs/show_bug.cgi?id=293098 Bug 293098].
 
* Examples of 3.x limitations
 
* Examples of 3.x limitations
** If you a run a job in a modal dialog, there is no jobs progress dialog and your only progress indicator is the status bar unless you happen to have the progress view open.
+
** Jobs and wizards/dialogs don't play well together
 +
***If you a run a job in a modal dialog, there is no jobs progress dialog and your only progress indicator is the status bar unless you happen to have the progress view open.
 +
***You can get weird blocking dialogs (See [https://bugs.eclipse.org/bugs/show_bug.cgi?id=276904 Bug 276904])
 
** Some constructs (DeferredTreeContentManager) use jobs and only know about certain progress contexts.  If I run a deferred fetch in a site, the site is adorned and the job progress is reported normally.  If I run the same viewer in a dialog, there is no local progress.
 
** Some constructs (DeferredTreeContentManager) use jobs and only know about certain progress contexts.  If I run a deferred fetch in a site, the site is adorned and the job progress is reported normally.  If I run the same viewer in a dialog, there is no local progress.
 
** If you run some operation synchronously and want to report failure, you have to decide in-line whether its logged, shown, or both, but that decision is not always known on the calling side.
 
** If you run some operation synchronously and want to report failure, you have to decide in-line whether its logged, shown, or both, but that decision is not always known on the calling side.
 
** If you want to show progress in multiple places, you have to wrap the monitor.  If you are using jobs this means defining your own framework so you can intercept the monitor on the run method and wrap it.
 
** If you want to show progress in multiple places, you have to wrap the monitor.  If you are using jobs this means defining your own framework so you can intercept the monitor on the run method and wrap it.
 +
* You can get broken if you call code that forks a job deep in the bowels of its implementation and your monitor wasn't expecting it.    See [https://bugs.eclipse.org/bugs/show_bug.cgi?id=282333 Bug 282333] and [https://bugs.eclipse.org/bugs/show_bug.cgi?id=244246 Bug 244246].
  
 
==e4 (Java)==
 
==e4 (Java)==

Revision as of 17:17, 29 October 2009

Based on a user's interaction with an application, the application may wish to schedule work to be done by other worker threads. The work that is done on these other worker threads may or may not be presented to the user. If background work is being invoked automatically based on some conditions, it may not necessarily be useful to present this information to the user. However, if the user explicitly invokes an action that causes a long-running operation to begin, they may wish to know about this so that they can respond accordingly when the operation has completed or just cancel the operation outright.

Eclipse 3.x API

In Eclipse 3.x, there are a variety of classes and interfaces that exposes progress reporting and work scheduling features.

  • org.eclipse.jface.operation.IRunnableContext
  • org.eclipse.ui.progress.IProgressService
  • org.eclipse.ui.progress.IWorkbenchSiteProgressService
  • org.eclipse.jface.operation.IRunnableWithProgress
  • org.eclipse.core.runtime.jobs.Job

Typically, for scheduling work to be completed by a worker thread, the Jobs framework is used.

Job aJob = new Job("My long-running operation...") {
  protected IStatus run(IProgressMonitor monitor) {
    // do stuff and report progress via the IPM
    return Status.OK_STATUS;
  }
};
// true to indicate that this job was initiated by a UI end user
aJob.setUser(true);

In the IProgressService and IWorkbenchSiteProgressService case, these are queried from the local service locator.

Critique:

  • You need to know how your code is going to be used (in a worker thread) at the time you create it (I need a Job).
  • You need to decide in the client code whether the user sees the job
  • We have no headless IRunnableWithProgress. (Today we have JFace IRunnableWithProgress, Job.run(IProgressMonitor), IDE's WorkspaceModifyOperation, Equinox future's IProgressRunnable). If we had a core-level IRunnableWithProgress then applications could define runnables that could be run in different runnable contexts (UI modal context, user job, future, etc.) Today the application has to define its own operations framework to handle these differences.
  • Likewise, we need a way to ensure that the runnables can be run in different runnable contexts (ie, a user job) with progress monitors and error reporting that is appropriate for where they are triggered. See Bug 293098.
  • Examples of 3.x limitations
    • Jobs and wizards/dialogs don't play well together
      • If you a run a job in a modal dialog, there is no jobs progress dialog and your only progress indicator is the status bar unless you happen to have the progress view open.
      • You can get weird blocking dialogs (See Bug 276904)
    • Some constructs (DeferredTreeContentManager) use jobs and only know about certain progress contexts. If I run a deferred fetch in a site, the site is adorned and the job progress is reported normally. If I run the same viewer in a dialog, there is no local progress.
    • If you run some operation synchronously and want to report failure, you have to decide in-line whether its logged, shown, or both, but that decision is not always known on the calling side.
    • If you want to show progress in multiple places, you have to wrap the monitor. If you are using jobs this means defining your own framework so you can intercept the monitor on the run method and wrap it.
  • You can get broken if you call code that forks a job deep in the bowels of its implementation and your monitor wasn't expecting it. See Bug 282333 and Bug 244246.

e4 (Java)

It would be nice to create a generic runnable (with progress. is it injected?)

IRunnable runnable = new Runnable("My long-running operation...") {
  protected IStatus run(IProgressMonitor monitor) {
    IStatus status = Status.OK_STATUS;
    monitor.beginTask("foo", 100);
    try {
       doFirstHalfFoo();
       monitor.worked(50);
       doSecondHalfFoo();
    } catch (FooException e) {
       status = new Status(IStatus.ERROR, "id", "foo failure message", e);
    } finally {
       monitor.done();
    }
    return status;
  }
};

Another alternative is that status and progress are both injected, so that there is no return status from the runnable itself. There is likely some relationship between the runnable context and how/where status is reported. Not sure who knows about who.

@Inject Provider<StatusHandler> statusHandler;
@Inject Provider<RunnableContext> runnableContext;
IRunnable runnable = new Runnable("My long-running operation...") {
  protected IStatus run() {
    IProgressMonitor monitor = runnableContext.get().getProgressMonitor();
    monitor.beginTask("foo", 100);
    try {
       doFirstHalfFoo();
       monitor.worked(50);
       doSecondHalfFoo();
    } catch (FooException e) {
       statusHandler.get().handle(e, "foo failure message", runnableContext.get().getStatusReportingService()); 
    } finally {
       monitor.done();
    }
  }
};

The runnable context defines

  • how something is run.
    • Synchronous (in current thread)
    • Modal (forked but blocking on result)
    • Asynchronously (in the background)
  • How progress is reported
  • How status is reported
  • Locks and scheduling rules (ISchedulingRule)
  • Batching of operations/notifications (IWorkspaceOperation)

Example contexts include:

  • wizard or dialog modal context (local progress and error reporting)
  • parts (adornment when busy or local progress, centralized error reporting via dialog?)
  • operations on a shared set of resources
  • jobs (not tied to any visible part, centralized error and progress reporting)
  • futures (same as above with post-processing)


The main idea here is that how the code is organized (the runnable) is separate from how progress and errors are reported, and you shouldn't have to know in advance when writing the code how your code will be run or where things get reported.

Questions:

  • Is there really a runnable context (implemented by various UI elements such as parts, wizards, etc.) Who is told to run the runnable and how?
  • Is a localized status and progress reporting service inferred by a particular kind of runnable context or is it injected, or is it obtained from the IEclipseContext?


Need to review the AC's meeting minutes prior to the creation of this e4 API.

Back to the top