Execution Contexts
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:
Coroutine Execution Context — available since 2024.2
Progress Indicator — obsolete since 2024.1
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 Coroutine Execution Context.
The following sections explain the contexts and provide information about process cancellation, progress tracking, and switching between contexts.
Coroutine Execution Context
Code executed in Kotlin coroutines is executed in the Coroutine Execution 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 Coroutine Execution 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 explicitly with blockingContext()
(in 2024.2+, it is effectively a no-operation function).
Background processes can be executed in three contexts:
Suspending Context (Coroutines) — available since 2024.1
Progress Indicator — obsolete since 2024.1
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.
Suspending Context (Coroutines)
Code executed in Kotlin coroutines is executed in the 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 the 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.
Blocking Context
Executing tasks in the Blocking Context means executing them on a thread without access to the coroutine context (basically, in non-suspending functions) and not under the 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.
Progress Indicator
Code executed via the Progress API (ProgressManager
, ProgressIndicator
, etc.) is executed in the Progress Indicator execution context. See the Progress API section for details.
Execution Contexts APIs
Cancellation Check
The following table presents APIs to use for checking whether a task was canceled in different execution contexts.
Coroutine Execution Context | |
---|---|
Progress Indicator |
Suspending Context |
|
---|---|
Blocking Context | |
Progress Indicator |
Progress Reporting
The following table presents the possibilities and APIs to use for reporting progress in different execution contexts.
Coroutine Execution Context |
Any
withBackgroundProgress(...) { // or other
// ...
reportProgress { reporter -> // or another report*Progress
// do tasks and report progress
}
// ...
}
|
---|---|
Progress Indicator |
See Background Processes: Tracking Progress for details. |
Suspending Context |
Any
withBackgroundProgress(...) { // or other
// ...
reportProgress { reporter -> // or another report*Progress
// do tasks and report progress
}
// ...
}
|
---|---|
Blocking Context | unavailable |
Progress Indicator |
See Background Processes: Tracking Progress for details. |
Switching Between Contexts
The following table presents the possibilities and APIs to use for switching between different execution contexts.
To Coroutine Execution Context | To Progress Indicator | ||
---|---|---|---|
From Coroutine Execution Context | - | ||
From Progress Indicator | - | ||
1 |
To Suspending Context | To Blocking Context | To Progress Indicator | |
---|---|---|---|
From Suspending Context | - |
| unavailable 3 |
From Blocking Context |
| - | unavailable 4 |
From Progress Indicator |
| unavailable | - |
1 2 3 4 |
It is only possible to:
switch from the Blocking Context or Progress Indicator to the Suspending Context
switch from the Suspending Context to the Blocking Context
The lack of an API for switching from Suspending and Blocking contexts to the Progress Indicator is intentional. Cancellable and trackable tasks should be run in coroutines as the Progress Indicator is obsolete since 2024.1.