The IntelliJ Platform provides APIs that allow tracking the progress of background processes and canceling their execution when they are canceled by a user, or they become obsolete due to some changes in the data model.
Available execution contexts differ depending on the IntelliJ Platform version. For the details, select the required tab below.
Background processes can be executed in two contexts:
Currently, the Progress Indicator context is the most widely used approach in the IntelliJ Platform. As the platform's execution model moves towards coroutines, this approach can be considered obsolete.
Starting with 2024.2, it is recommended to execute new code in the Job context.
The following sections explain the contexts and provide information about process cancellation, progress tracking, and switching between contexts.
Code executed in Kotlin coroutines is executed in the Job context. Since 2024.2, coroutines are recommended for executing background tasks to maximize CPU utilization. Note that executing code in coroutines is possible only with Kotlin.
While code executed in the Job context should use suspending functions,
sometimes it is required to call non-suspending/blocking APIs that use methods such as
ProgressManager.checkCanceled()
or ModalityState.defaultModalityState()
.
Since 2024.2, these methods work as expected without the need to switch to the blocking context.
Job
class, which is used for task cancellation in suspending and non-suspending
functions.
Inspection
Background processes can be executed in three contexts:
Currently, the Progress Indicator context is the most widely used approach in the IntelliJ Platform. As the platform's execution model moves towards coroutines, this approach can be considered obsolete.
Starting with 2024.1, it is recommended to execute new code in the suspending context.
The following sections explain the contexts and provide information about process cancellation, progress tracking, and switching between contexts.
Code executed in Kotlin coroutines is executed in a suspending context. Since 2024.1, this context is recommended for executing background tasks to maximize CPU utilization. Note that executing code in coroutines is possible only with Kotlin.
In a suspending context, methods such as ProgressManager.checkCanceled()
or ModalityState.defaultModalityState()
won't have any effect.
Therefore, if their behavior is required, switch to a blocking
context.
Inspection
Executing tasks in a blocking context means executing them on a thread without access to the coroutine context (basically, in non-suspending functions) and not under a progress indicator. Such tasks can still be canceled, but they can't report progress.
Plugins should not execute new code in the blocking context. Always prefer executing tasks in the suspending context or under the progress indicator if a plugin cannot use Kotlin.
Functions which schedule execution via Application.executeOnPooledThread()
and similar methods, and which rely on ProgressManager.checkCanceled()
should be annotated with @RequiresBlockingContext
to inform clients about the required switch to a blocking context.
Inspection
Code executed via the Progress API
(ProgressManager
,
ProgressIndicator
,
etc.)
is executed in a progress indicator context.
See the section for details.
Executing code under the progress indicator is obsolete since 2024.1. It is advised to use Kotlin coroutines in new code.
Please note that obsolete status does not mean deprecation. Executing code using the Progress API is still allowed, but coroutines are recommended as a more performant solution.
The following table presents APIs to use for checking whether a task was canceled in different execution contexts.
Job Context | |
Progress Indicator |
Suspending Context |
ensureActive()
from Kotlin coroutine's APIProgressManager.checkCanceled()
does not work in the suspending context.
To enable it,
switch to blockingContext() ,
if it is not possible to change the code.
|
Blocking Context | |
Progress Indicator |
The following table presents the possibilities and APIs to use for reporting progress in different execution contexts.
Job Context |
ProgressStep
- a step-based progress reporting (see its KDoc for details)
RawProgressReporter
- a raw text, details, and fraction reporting (invoked via reportRawProgress() )
Any |
Progress Indicator |
ProgressIndicator 's
or ProgressManager 's
methods
See Background Processes: Tracking Progress for details. |
Suspending Context |
ProgressStep
- a step-based progress reporting (see its KDoc for details)
RawProgressReporter
- a raw text, details, and fraction reporting (invoked via reportRawProgress() )
Any |
Blocking Context | unavailable |
Progress Indicator |
ProgressIndicator 's
or ProgressManager 's
methods
See Background Processes: Tracking Progress for details. |
The following table presents the possibilities and APIs to use for switching between different execution contexts.
To Job Context | To Progress Indicator | ||
From Job Context | - |
coroutineToIndicator() 1 |
|
From Progress Indicator |
runBlockingCancellable() |
- | |
1
coroutineToIndicator()
is an experimental API, which was originally internal and created to aid
platform migration.
It is not recommended to switch from the Job context to the progress indicator.
Use it only if there is no other option.
|
To Suspending Context | To Blocking Context | To Progress Indicator | |
From Suspending Context | - | blockingContext() 1 |
unavailable 3 |
From Blocking Context | runBlockingCancellable() 2 |
- | unavailable 4 |
From Progress Indicator | runBlockingCancellable() 2 |
unavailable | - |
1
blockingContext()
enables ProgressManager.checkCanceled() , forwards modality state, etc.
It has an opposite behavior to runBlockingCancellable() .
Since 2024.2, it is a no-operation function, as the blocking context was unified
with the suspending context into the Job context.
2 runBlockingCancellable()
has an opposite behavior to blockingContext()
3 coroutineToIndicator()
is an internal API to aid platform migration
4 blockingContextToIndicator()
is an internal API to aid platform migration
|
It is only possible to:
The lack of an API for switching from suspending and blocking contexts to progress indicator is intentional. Cancellable and trackable tasks should be run in coroutines as the progress indicator is obsolete since 2024.1.