Hello everyone!
We would like to share with you important updates of the threading framework in IntelliJ Platform 2025.2.
The most notable change of this release is that we are starting to execute some write actions on background. This functionality still remains internal, as we need to ensure that the Platform works smoothly with this new setup. For now, only certain write actions on project startup are changed for background execution. Write actions on UI thread will be supported further.
If you feel that it brings any problems, consider setting the system property -Didea.background.write.action.enabled=false
for your IDE. Typical example of problems is that some of the listeners for MessageBus topics that were meant to run on EDT may run on background threads. Don’t hesitate to reach out if you have any feedback.
Other changes in the threading framework:
- If a thread is blocked on acquisition of the Read/Write lock, then it will react to external cancellation and throw an instance of
CancellationException
without proceeding further. This is similar to prompt cancellation guarantee from kotlin coroutines library.
It means that the following code:
coroutineScope {
launch(Dispatchers.EDT) {
runWriteAction {
// long operation
}
}
val job = launch(Dispatchers.Default) {
runReadAction {}
}
job.cancelAndJoin() // <- this will be promptly completed because lock acquisition in `runReadAction` is now cancellable.
}
-
suspend fun readAction
is no longer rescheduled withinvokeLater
(IJPL-186444). It may cause increased number of cancellations in your code. Unfortunately there is no easy way to diagnose it, but replacingreadAction
withrunReadAction
may help. -
Sometimes you may see deadlocks that mention
blockingWaitForCompositeFileOpen
. Most likely, it means that you are opening a file under write lock (like incom.intellij.openapi.fileEditor.FileNavigator#navigate
). In this case, consider making opening of the file asynchronous, i.e., surround your navigation logic withApplication.invokeLater
. -
ApplicationListener.beforeWriteActionStart
,ApplicationListener.writeActionStarted
,ApplicationListener.writeActionFinished
,ApplicationListener.afterWriteActionFinished
now may be invoked on a background thread instead of only EDT. Consider removing access to UI from your listeners or delay it withApplication.invokeLater
. -
currentThreadCoroutineScope
is now stable and it can be invoked only when there is an outerwithCurrentThreadCoroutineScope
. It is fine to continue using this function insideAnAction.actionPerformed
. -
Functions
runBlockingCancellable
,currentThreadCoroutineScope
, andcoroutineToIndicator
are promoted to stable. -
blockingContext
is now no-op and deprecated (IJPL-445). Since 2025.2 IntelliJ platform manages thread contexts automatically.