Class ProgressMonitors

java.lang.Object
com._1c.g5.v8.dt.common.runtime.ProgressMonitors

public class ProgressMonitors extends Object
Utilities to work with tasks, sub-tasks and progress monitors.

The contracts of IProgressMonitor and SubMonitor are not easy to understand and follow correctly. Frequently their API is misused. The goal of the class is to make it simple to correctly follow the contract anticipated by Eclipse developers.

  1. Use computeAsTask(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.ComputableWithSubMonitor<T, E1, E2>) / runAsTask(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.RunnableWithSubMonitor<E1, E2>) at the top of the stack in action handler, event handler or a job to denote start of a task.
  2. Use computeWithSubMonitor(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.ComputableWithSubMonitor<T, E1, E2>) / runWithSubMonitor(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.RunnableWithSubMonitor<E1, E2>) whenever you get IProgressMonitor as a method parameter and do with it something more than just passing it through to a single other method. Specify a name in potentially long running methods of public API of services to denote sub-task start. Otherwise, leave name as null.
  3. Use computeInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>) / runInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleRunnableSubTask<E1, E2>) when you have multiple long steps in a current method to denote separate sub-tasks. Usually sub-tasks reflect structure of a task rather than processing of multiple resources in a batch.
  4. Use computeInStep(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>) / runInStep(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleRunnableSubTask<E1, E2>) when you have a number of items to process as a part of a sub-task. While sub-tasks reflect structure of a task, it is step that represents processing of individual item like a file, resource, configuration object and so on within a set of multiple such items.
There are two families of methods:
  • Those that start with run return no value, just execute some action.
  • Those that start with compute return a value so you have to pass something that returns it too.

If tracing is enabled via CommonPlugin.TRACE_DEBUG, CommonPlugin.TRACE_PROGRESS_TASKS, CommonPlugin.TRACE_PROGRESS_SUBTASKS and CommonPlugin.TRACE_PROGRESS_STEPS then a record will be logged when task, sub-task or step starts or ends and how long it took to run it. If CommonPlugin.isDebugging() is enabled then potential issues with progress reporting will be logged as warnings.

  • Method Details

    • computeAsTask

      public static <T, E1 extends Throwable, E2 extends Throwable> T computeAsTask(String name, int childrenTicks, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.ComputableWithSubMonitor<T,E1,E2> codeBlock) throws E1, E2
      Begins a task that computes a value.

      The method should be called at the top of the stack where a task actually begins. This is usually either job, action handler or event handler. The method should not be called multiple times for the same root progress monitor. You should not generally call the method from service implementations, protected methods and so on where you do not control if task has already began. For sub-tasks see computeInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>).

      Calling the method, creates new SubMonitor from the specified IProgressMonitor, allocates ticks for childrens and sets name of the task. An actual code to run will get this sub-monitor as a parameter and should use it instead of the original progress monitor. Both original monitor and sub-monitor automatically get IProgressMonitor.done() before the method returns (successfully or erroneously).

      When calling another method inside the code block and have to pass to this method an instance of IProgressMonitor then use either SubMonitor.newChild(int)/SubMonitor.split(int) (using the sub monitor you have received as a parameter of the code block) or computeWithSubMonitor(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.ComputableWithSubMonitor<T, E1, E2>)/computeInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>). Avoid using IProgressMonitor.slice(int) on sub monitor as it behaves not exactly straightforward. Prefer SubMonitor.split(int) as it automatically checks for cancellation and will throw OperationCanceledException.

      
       progressMonitorDialog.run(true, true, monitor -> {
          int result = ProgressMonitors.computeAsTask(Messages.Task1_name, 100, monitor, subMonitor -> {
             method1(subMonitor.newChild(10));
             method2(subMonitor.newChild(10));
             return method3(subMonitor.newChild(80));
          });
       });
       
      Type Parameters:
      T - Type of the returned value.
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the task being started. This should be a localized string that could be presented to user. Must not be null.
      childrenTicks - Number of ticks to allocate for childred. Use IProgressMonitor.UNKNOWN if you do not know amount of work.
      monitor - Parent progress monitor or null if was none or nothing is to be reported. This monitor should not be used inside the code block or by caller once the method returns.
      codeBlock - Code that computes a value. It gets new sub-monitor as a parameter. Must not be null.
      Returns:
      The same value as the code block returns.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • runAsTask

      public static <E1 extends Throwable, E2 extends Throwable> void runAsTask(String name, int childrenTicks, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.RunnableWithSubMonitor<E1,E2> codeBlock) throws E1, E2
      Begins a task that runs an action.

      The method should be called at the top of the stack where a task actually begins. This is usually either job, action handler or event handler. The method should not be called multiple times for the same root progress monitor. You should not generally call the method from service implementations, protected methods and so on where you do not control if task has already began. For sub-tasks see computeInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>).

      Calling the method, creates new SubMonitor from the specified IProgressMonitor, allocates ticks for childrens and sets name of the task. An actual code to run will get this sub-monitor as a parameter and should use it instead of the original progress monitor. Both original monitor and sub-monitor automatically get IProgressMonitor.done() before the method returns (successfully or erroneously).

      When calling another method inside the code block and have to pass to this method an instance of IProgressMonitor then use either SubMonitor.newChild(int)/SubMonitor.split(int) (using the sub monitor you have received as a parameter of the code block) or runWithSubMonitor(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.RunnableWithSubMonitor<E1, E2>)/runInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleRunnableSubTask<E1, E2>). Avoid using IProgressMonitor.slice(int) on sub monitor as it behaves not exactly straightforward. Prefer SubMonitor.split(int) as it automatically checks for cancellation and will throw OperationCanceledException.

      
       progressMonitorDialog.run(true, true, monitor -> {
          ProgressMonitors.runAsTask(Messages.Task1_name, 100, monitor, subMonitor -> {
             method1(subMonitor.newChild(10));
             method2(subMonitor.newChild(10));
             method3(subMonitor.newChild(80));
          });
       });
       
      Type Parameters:
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the task being started. This should be a localized string that could be presented to user. Must not be null.
      childrenTicks - Number of ticks to allocate for childred. Use IProgressMonitor.UNKNOWN if you do not know amount of work.
      monitor - Parent progress monitor or null if was none or nothing is to be reported. This monitor should not be used inside the code block or by caller once the method returns.
      codeBlock - An action to run. It gets new sub-monitor as a parameter. Must not be null.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • computeWithSubMonitor

      public static <T, E1 extends Throwable, E2 extends Throwable> T computeWithSubMonitor(String name, int childrenTicks, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.ComputableWithSubMonitor<T,E1,E2> codeBlock) throws E1, E2
      Computes a value using sub-monitor.

      The method should wrap body of methods receiving IProgressMonitor. It creates child SubMonitor that is passed as a parameter to the wrapped code block. Both original parent progress monitor and newly created child sub-monitor automatically get IProgressMonitor.done() before the method returns (successfully or erroneously).

      If name was specified then it will be set as a sub-task name before the code block is executed. In this case, once the code block finishes execution, sub-task name will be reset (to an empty string rather than to an old sub-task name). Because of this, consider specifying the name when implementing public API methods of services when they take long time to execute but avoid specifying name for non-public methods and non-services to avoid unintently resetting sub-task name because of something short and unimportant.

      When calling another method inside the code block and have to pass to this method an instance of IProgressMonitor then use either SubMonitor.newChild(int)/SubMonitor.split(int) (using the sub monitor you have received as a parameter of the code block) or computeWithSubMonitor(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.ComputableWithSubMonitor<T, E1, E2>)/computeInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>). Avoid using IProgressMonitor.slice(int) on sub monitor as it behaves not exactly straightforward. Prefer SubMonitor.split(int) as it automatically checks for cancellation and will throw OperationCanceledException.

      
       public int myPublicApiMethod(IProgressMonitor monitor) {
           return computeWithSubMonitor(Messages.Subtask1_name, 100, monitor, subMonitor -> {
               method1(subMonitor.newChild(10));
               method2(subMonitor.newChild(10));
               return method3(subMonitor.newChild(80));
           });
       }
       private int somePrivateMethod(IProgressMonitor monitor) {
           return computeWithSubMonitor(null, 1, monitor, subMonitor -> {
               return otherClassInstance.otherMethod(subMonitor.newChild(1));
           });
       }
       
      Type Parameters:
      T - Type of the returned value.
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the sub-task being started (case of service public API that runs for long) or null if sub-task name is not to be affected (everything else). If not null then this should be a localized string that could be presented to user.
      childrenTicks - Number of ticks to allocate for childred. Use IProgressMonitor.UNKNOWN if you do not know amount of work.
      monitor - Parent progress monitor or null if was none or nothing is to be reported. This monitor should not be used inside the code block or by caller once the method returns.
      codeBlock - Code that computes a value. It gets new sub-monitor as a parameter. Must not be null.
      Returns:
      The same value as the code block returns.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • runWithSubMonitor

      public static <E1 extends Throwable, E2 extends Throwable> void runWithSubMonitor(String name, int childrenTicks, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.RunnableWithSubMonitor<E1,E2> codeBlock) throws E1, E2
      Runs an action using sub-monitor.

      The method should wrap body of methods receiving IProgressMonitor. It creates child SubMonitor that is passed as a parameter to the wrapped code block. Both original parent progress monitor and newly created child sub-monitor automatically get IProgressMonitor.done() before the method returns (successfully or erroneously).

      If name was specified then it will be set as a sub-task name before the code block is executed. In this case, once the code block finishes execution, sub-task name will be reset (to an empty string rather than to an old sub-task name). Because of this, consider specifying the name when implementing public API methods of services when they take long time to execute but avoid specifying name for non-public methods and non-services to avoid unintently resetting sub-task name because of something short and unimportant.

      When calling another method inside the code block and have to pass to this method an instance of IProgressMonitor then use either SubMonitor.newChild(int)/SubMonitor.split(int) (using the sub monitor you have received as a parameter of the code block) or runWithSubMonitor(java.lang.String, int, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.RunnableWithSubMonitor<E1, E2>)/runInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleRunnableSubTask<E1, E2>). Avoid using IProgressMonitor.slice(int) on sub monitor as it behaves not exactly straightforward. Prefer SubMonitor.split(int) as it automatically checks for cancellation and will throw OperationCanceledException.

      
       public void myPublicApiMethod(IProgressMonitor monitor) {
           runWithSubMonitor(Messages.Subtask1_name, 100, monitor, subMonitor -> {
               method1(subMonitor.newChild(10));
               method2(subMonitor.newChild(10));
               method3(subMonitor.newChild(80));
           });
       }
       private void somePrivateMethod(IProgressMonitor monitor) {
           runWithSubMonitor(null, 1, monitor, subMonitor -> {
               otherClassInstance.otherMethod(subMonitor.newChild(1));
           });
       }
       
      Type Parameters:
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the sub-task being started (case of service public API that runs for long) or null if sub-task name is not to be affected (everything else). If not null then this should be a localized string that could be presented to user.
      childrenTicks - Number of ticks to allocate for childred. Use IProgressMonitor.UNKNOWN if you do not know amount of work.
      monitor - Parent progress monitor or null if was none or nothing is to be reported. This monitor should not be used inside the code block or by caller once the method returns.
      codeBlock - An action to run. It gets new sub-monitor as a parameter. Must not be null.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • computeInSubTask

      public static <T, E1 extends Throwable, E2 extends Throwable> T computeInSubTask(String name, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.SimpleComputableSubTask<T,E1,E2> codeBlock) throws E1, E2
      Wraps code block computing a value with a sub-task.

      The method does not manage creation or work done of parent or child monitors. Moreover, no child monitor is created. The only thing done is setting sub-task name before the code block is executed and then clearing sub-task name after the code block has finished executing (successfully or erroneously). This clearing of sub-task name is important to ensure that user is not confused seeing task name that has been actually finished long ago while waiting for something else.

      The method could be useful when running a long computation right inside the current method:

      
       int result1 = ProgressMonitors.computeInSubTask(Messages.Subtask1_name, monitor, () -> {
           Thread.sleep(1000);
           return 1;
       });
       int result2 = ProgressMonitors.computeInSubTask(Messages.Subtask2_name, monitor, () -> {
           Thread.sleep(1000);
           return 2;
       });
       
      Type Parameters:
      T - Type of the returned value.
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the sub-task being started. This should be a localized string that could be presented to user. Must not be null.
      monitor - Progress monitor with which to report subtask or null if was none or nothing is to be reported (the code block is executed anyway).
      codeBlock - Code that computes a value. Must not be null.
      Returns:
      The same value as the code block returns.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • runInSubTask

      public static <E1 extends Throwable, E2 extends Throwable> void runInSubTask(String name, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.SimpleRunnableSubTask<E1,E2> codeBlock) throws E1, E2
      Wraps code block running an action with a sub-task.

      The method does not manage creation or work done of parent or child monitors. Moreover, no child monitor is created. The only thing done is setting sub-task name before the code block is executed and then clearing sub-task name after the code block has finished executing (successfully or erroneously). This clearing of sub-task name is important to ensure that user is not confused seeing task name that has been actually finished long ago while waiting for something else.

      The method could be useful when running a long action right inside the current method:

      
       ProgressMonitors.runInSubTask(Messages.Subtask1_name, monitor, () -> {
           Thread.sleep(1000);
       });
       ProgressMonitors.runInSubTask(Messages.Subtask2_name, monitor, () -> {
           Thread.sleep(1000);
       });
       
      Type Parameters:
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the task being started. This should be a localized string that could be presented to user. Must not be null.
      monitor - Progress monitor with which to report subtask or null if was none or nothing is to be reported (the code block is executed anyway).
      codeBlock - Code that runs an action. Must not be null.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • computeInStep

      public static <T, E1 extends Throwable, E2 extends Throwable> T computeInStep(String name, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.SimpleComputableSubTask<T,E1,E2> codeBlock) throws E1, E2
      Wraps code block computing a value with a step of a sub-task.

      While computeInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleComputableSubTask<T, E1, E2>) should be used to reflect structure of the task, this method should be used to wrap arbitrary potentially high number of steps within a sub-task. For example, updating infobase (task) could involve exporting configuration (sub-task) and each file to export is a step that could be wrapped with this method. The rules for tracking tasks, sub-tasks and steps within sub-tasks could be different.

      The method does not manage creation or work done of parent or child monitors. Moreover, no child monitor is created. The only thing done is setting sub-task name before the code block is executed and then clearing sub-task name after the code block has finished executing (successfully or erroneously). This clearing of sub-task name is important to ensure that user is not confused seeing task name that has been actually finished long ago while waiting for something else.

      The method could be useful when reporting execution of high number of steps:

      
       for(File file : files) {
           int result = ProgressMonitors.computeInStep(file.toString(), monitor, () -> {
               processFile(file);
           });
       }
       
      Type Parameters:
      T - Type of the returned value.
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the step being started. This should be a localized string that could be presented to user. Must not be null.
      monitor - Progress monitor with which to report subtask or null if was none or nothing is to be reported (the code block is executed anyway).
      codeBlock - Code that computes a value. Must not be null.
      Returns:
      The same value as the code block returns.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.
    • runInStep

      public static <E1 extends Throwable, E2 extends Throwable> void runInStep(String name, org.eclipse.core.runtime.IProgressMonitor monitor, ProgressMonitors.SimpleRunnableSubTask<E1,E2> codeBlock) throws E1, E2
      Wraps code block running an action with a step of a sub-task.

      While runInSubTask(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, com._1c.g5.v8.dt.common.runtime.ProgressMonitors.SimpleRunnableSubTask<E1, E2>) should be used to reflect structure of the task, this method should be used to wrap arbitrary potentially high number of steps within a sub-task. For example, updating infobase (task) could involve exporting configuration (sub-task) and each file to export is a step that could be wrapped with this method. The rules for tracking tasks, sub-tasks and steps within sub-tasks could be different.

      The method does not manage creation or work done of parent or child monitors. Moreover, no child monitor is created. The only thing done is setting sub-task name before the code block is executed and then clearing sub-task name after the code block has finished executing (successfully or erroneously). This clearing of sub-task name is important to ensure that user is not confused seeing task name that has been actually finished long ago while waiting for something else.

      The method could be useful when reporting execution of high number of steps:

      
       for(File file : files) {
           ProgressMonitors.runInStep(file.toString(), monitor, () -> {
               processFile(file);
           });
       }
       
      Type Parameters:
      E1 - Type of Exception thrown.
      E2 - Type of Exception thrown.
      Parameters:
      name - Name of the task being started. This should be a localized string that could be presented to user. Must not be null.
      monitor - Progress monitor with which to report subtask or null if was none or nothing is to be reported (the code block is executed anyway).
      codeBlock - Code that runs an action. Must not be null.
      Throws:
      E1 - The same exception as the code block throws.
      E2 - The same exception as the code block throws.