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.
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.
Once the client code switches to a suspending or a blocking context, it should not switch back to a progress indicator context.
The following sections explain the contexts and provide information about process cancellation, progress tracking, and switching between different contexts.
Suspending Context
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.
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.
Cancellation Check
ensureActive()
from Kotlin coroutine's API
Progress Reporting
ProgressStep
- a step-based progress reporting (see its KDoc for details)RawProgressReporter
- a raw text, details, and fraction reporting (invoked viareportRawProgress()
)
Any report*Progress()
function should be used inside with*Progress()
or runWithModalProgressBlocking()
. Otherwise, if there is no reporter in the context, using report*Progress()
will have no effect.
Switching to Other Contexts
to blocking context:
blockingContext()
- enablesProgressManager.checkCanceled()
, forwards modality state, etc. This function has an opposite behavior torunBlockingCancellable()
.to progress indicator: unavailable (
coroutineToIndicator()
is an internal API and exists only to aid platform migration)
Blocking Context
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't be canceled by using coroutines' or progress indicator's cancellation capabilities, which may block threads and consume resources even if the task is no longer relevant.
Usually, 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.
Cancellation Check
Progress Reporting
Progress reporting is not available in the blocking context.
Switching to Other Contexts
to coroutine:
runBlockingCancellable()
. This function has an opposite behavior toblockingContext()
.to progress indicator: unavailable (
blockingContextToIndicator()
is an internal API and exists only to aid platform migration)
Progress Indicator
Code executed via the Progress API (ProgressManager
, ProgressIndicator
, etc.) is executed in a progress indicator context. See the Progress API section for details.
Cancellation Check
ProgressManager.checkCanceled()
- as described in the Cancellation section
Progress Reporting
current thread's
ProgressIndicator
methodsProgressManager
'sprogress
andprogress2
static methods
Switching to Other Contexts
to coroutine:
runBlockingCancellable
to blocking: unavailable