mirror of
https://github.com/JetBrains/intellij-sdk-code-samples.git
synced 2025-07-28 01:07:49 +08:00
Use consistent terms: "UI thread" -> "EDT"
This commit is contained in:
parent
8cad5df3dc
commit
c8f2bfdcf6
@ -99,7 +99,7 @@ gantt
|
||||
suspendingTask() : 2, 3
|
||||
section Thread 2
|
||||
suspendingTask() : 0, 1
|
||||
section UI Thread
|
||||
section EDT
|
||||
updateUI() : 3, 4
|
||||
```
|
||||
|
||||
@ -107,7 +107,7 @@ The code is executed as follows:
|
||||
1. `suspendingTask` is started and partially executed on **Thread 2**.
|
||||
2. `suspendingTask` is suspended when it waits for data fetched from the internet.
|
||||
3. After receiving data, `suspendingTask` is resumed, but now it is executed on **Thread 1**.
|
||||
4. Execution explicitly switches to the EDT dispatcher and `updateUI` is executed on the UI thread.
|
||||
4. Execution explicitly switches to the EDT dispatcher and `updateUI` is executed on EDT.
|
||||
|
||||
|
||||
> This behavior can result in unexpected consequences for code that relies on thread-specific data and assumes it will execute consistently on the same thread.
|
||||
|
@ -44,7 +44,7 @@ WARA doesn't need the following API methods:
|
||||
- `executeSynchronously()` because effectively they are executed in the current coroutine dispatcher already
|
||||
- `expireWhen(BooleanSupplier expireCondition)`/`expireWith(Disposable parentDisposable)`/`wrapProgress(ProgressIndicator progressIndicator)` because they are canceled when the calling coroutine is canceled
|
||||
- `finishOnUiThread()` because this is handled by switching to the [EDT dispatcher](coroutine_dispatchers.md#edt-dispatcher).
|
||||
Note that the UI data must be pure (e.g., strings/icons/element pointers), which inherently cannot be invalidated during the transfer from a background thread to the UI thread.
|
||||
Note that the UI data must be pure (e.g., strings/icons/element pointers), which inherently cannot be invalidated during the transfer from a background thread to EDT.
|
||||
- `coalesceBy(Object ... equality)` because this should be handled by [`Flow.collectLatest()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect-latest.html) and/or [`Flow.distinctUntilChanged()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/distinct-until-changed.html).
|
||||
Usually, NBRAs are run as a reaction to user actions, and there might be multiple NBRAs running, even if their results are unused.
|
||||
Instead of cancelling the read action, in the coroutine world the coroutines are canceled:
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
This section presents techniques to use coroutines efficiently and avoid common pitfalls.
|
||||
|
||||
## Switching Between the Background and UI Threads
|
||||
## Switching Between the Background Threads and EDT
|
||||
|
||||
Avoid the `invokeLater`-style often found in Java:
|
||||
|
||||
@ -166,7 +166,7 @@ cs.launch(ModalityState.current().asContextElement()) {
|
||||
}
|
||||
```
|
||||
|
||||
It is possible that the coroutine is launched as a response to a user event from the UI thread, where `ModalityState.current()` is available.
|
||||
It is possible that the coroutine is launched as a response to a user event from EDT, where `ModalityState.current()` is available.
|
||||
|
||||
If the coroutine is launched from a background thread, then it should not be invoked on top of an unrelated dialog anyway.
|
||||
The absence of the context modality state is effectively equivalent to specifying `ModalityState.nonModal()`.
|
||||
|
@ -36,7 +36,7 @@ Reading data is allowed from any thread.
|
||||
|
||||
Read operations need to be wrapped in a read action (RA) if not invoked via `Application.invokeLater()`.
|
||||
|
||||
If invoked from a non-UI thread or from the UI thread but via `SwingUtilities.invokeLater()`, it must be explicitly wrapped in a read action (RA).
|
||||
If invoked from a background thread or from EDT but via `SwingUtilities.invokeLater()`, it must be explicitly wrapped in a read action (RA).
|
||||
|
||||
</tab>
|
||||
|
||||
@ -44,7 +44,7 @@ If invoked from a non-UI thread or from the UI thread but via `SwingUtilities.in
|
||||
|
||||
Reading data is allowed from any thread.
|
||||
|
||||
Reading data from the UI thread does not require any special effort.
|
||||
Reading data from EDT does not require any special effort.
|
||||
|
||||
However, read operations performed from any other thread must be wrapped in a read action (RA).
|
||||
|
||||
@ -62,7 +62,7 @@ As a rule of thumb, whenever starting a read action, check if the PSI/VFS/projec
|
||||
|
||||
### Write Access
|
||||
|
||||
Writing data is only allowed from the UI thread, and write operations always need to be wrapped in a write action (WA).
|
||||
Writing data is only allowed from EDT, and write operations always need to be wrapped in a write action (WA).
|
||||
|
||||
Modifying the model is only allowed from write-safe contexts, including user actions and `SwingUtilities.invokeLater()` calls from them (see [](#modality-and-invokelater)).
|
||||
|
||||
@ -75,10 +75,10 @@ You may not modify PSI, VFS, or project model from inside UI renderers or `Swing
|
||||
|
||||
## Modality and `invokeLater()`
|
||||
|
||||
To pass control from a background thread to the [Event Dispatch Thread](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) (EDT), instead of the standard `SwingUtilities.invokeLater()`, plugins should use `ApplicationManager.getApplication().invokeLater()`.
|
||||
To pass control from a background thread to EDT, instead of the standard `SwingUtilities.invokeLater()`, plugins should use `ApplicationManager.getApplication().invokeLater()`.
|
||||
The latter API allows specifying the _modality state_ ([`ModalityState`](%gh-ic%/platform/core-api/src/com/intellij/openapi/application/ModalityState.java)) for the call, i.e., the stack of modal dialogs under which the call is allowed to execute:
|
||||
|
||||
#### `ModalityState.nonModal()` / `NON_MODAL`
|
||||
### `ModalityState.nonModal()` / `NON_MODAL`
|
||||
|
||||
The operation will be executed after all modal dialogs are closed.
|
||||
If any of the open (unrelated) projects displays a per-project modal dialog, the action will be performed after the dialog is closed.
|
||||
@ -90,7 +90,7 @@ The operation can be executed when the topmost shown dialog is the one that cont
|
||||
### None Specified
|
||||
|
||||
`ModalityState.defaultModalityState()` will be used.
|
||||
This is the optimal choice in most cases that uses the current modality state when invoked from UI thread.
|
||||
This is the optimal choice in most cases that uses the current modality state when invoked from EDT.
|
||||
It has special handling for background processes started with `ProgressManager`: `invokeLater()` from such a process may run in the same dialog that the process started.
|
||||
|
||||
### `ModalityState.any()`
|
||||
@ -98,7 +98,7 @@ It has special handling for background processes started with `ProgressManager`:
|
||||
The operation will be executed as soon as possible regardless of modal dialogs.
|
||||
Please note that modifying PSI, VFS, or project model is prohibited from such runnables.
|
||||
|
||||
If a UI thread activity needs to access [file-based index](indexing_and_psi_stubs.md) (e.g., it's doing any project-wide PSI analysis, resolves references, etc.), please use `DumbService.smartInvokeLater()`.
|
||||
If EDT activity needs to access [file-based index](indexing_and_psi_stubs.md) (e.g., it's doing any project-wide PSI analysis, resolves references, etc.), please use `DumbService.smartInvokeLater()`.
|
||||
That way, it is run after all possible indexing processes have been completed.
|
||||
|
||||
## Background Processes and `ProcessCanceledException`
|
||||
@ -146,7 +146,7 @@ These actions are available only if [Internal Mode is enabled](enabling_internal
|
||||
## Read Action Cancellability
|
||||
|
||||
Background threads shouldn't take plain read actions for a long time.
|
||||
The reason is that if the UI thread needs a write action (e.g., the user types something), it must be acquired as soon as possible.
|
||||
The reason is that if EDT needs a write action (e.g., the user types something), it must be acquired as soon as possible.
|
||||
Otherwise, the UI will freeze until all background threads have released their read actions.
|
||||
|
||||
The best-known approach is to cancel background read actions whenever there's a write action about to occur, and restart that background read action later from scratch.
|
||||
@ -157,7 +157,7 @@ The next time the background thread calls `checkCanceled()`, a PCE is thrown, an
|
||||
|
||||
There are two recommended ways of doing this:
|
||||
|
||||
* If on UI thread, call [`ReadAction.nonBlocking()`](%gh-ic%/platform/core-api/src/com/intellij/openapi/application/ReadAction.java) which returns [`NonBlockingReadAction`](%gh-ic%/platform/core-api/src/com/intellij/openapi/application/NonBlockingReadAction.java) (NBRA)
|
||||
* If on EDT, call [`ReadAction.nonBlocking()`](%gh-ic%/platform/core-api/src/com/intellij/openapi/application/ReadAction.java) which returns [`NonBlockingReadAction`](%gh-ic%/platform/core-api/src/com/intellij/openapi/application/NonBlockingReadAction.java) (NBRA)
|
||||
* If already in a background thread, use [`ProgressManager.runInReadActionWithWriteActionPriority()`](%gh-ic%/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java) in a loop, until it passes or the whole activity becomes obsolete.
|
||||
|
||||
In both approaches, always check at the start of each read action if the objects are still valid, and if the whole operation still makes sense (i.e., not canceled by the user, the project isn't closed, etc.).
|
||||
@ -167,7 +167,7 @@ If the activity has to access [file-based index](indexing_and_psi_stubs.md) (e.g
|
||||
|
||||
## Avoiding UI Freezes
|
||||
|
||||
#### Do not Perform Long Operations in UI Thread
|
||||
#### Do not Perform Long Operations in EDT
|
||||
|
||||
In particular, don't traverse [](virtual_file_system.md), parse [PSI](psi.md), resolve [references](psi_references.md) or query [indexes/stubs](indexing_and_psi_stubs.md).
|
||||
|
||||
@ -176,7 +176,7 @@ Meanwhile, please try to speed up what you can in your plugin as it will be gene
|
||||
For implementations of [`AnAction`](%gh-ic%/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java), plugin authors should specifically
|
||||
review the documentation of `AnAction.getActionUpdateThread()` in the [](basic_action_system.md) section as it describes how threading works for actions.
|
||||
|
||||
`WriteAction`s currently have to happen on UI thread.
|
||||
`WriteAction`s currently have to happen on EDT.
|
||||
To speed them up, as much as possible should be moved out of the write action into a preparation step which can be then invoked in the background (e.g., using `ReadAction.nonBlocking()`, see above).
|
||||
|
||||
#### Event Listeners
|
||||
|
@ -72,7 +72,7 @@ The method `AnAction.update()` is periodically called by the IntelliJ Platform i
|
||||
The `update()` method gives an action to evaluate the current context and enable or disable its functionality.
|
||||
Implementors must ensure that changing presentation and availability status handles all variants and state transitions; otherwise, the given Action will get "stuck".
|
||||
|
||||
> The `AnAction.update()` method can be called frequently and on a UI thread.
|
||||
> The `AnAction.update()` method can be called frequently and on EDT.
|
||||
> It must _execute very quickly_; no real work must be performed.
|
||||
> For example, checking selection in a tree or a list is considered valid, but working with the file system is not.
|
||||
>
|
||||
|
@ -53,7 +53,7 @@ The initial phase describes what happens when no parameter info is currently dis
|
||||
2. If the returned function call element is valid, the `showParameterInfo()` method is invoked.
|
||||
Implementations of this method usually just call `showHint()` of the `CreateParameterInfoContext` providing the offset at which the popup should appear.
|
||||
3. For each item to show from step 1, the `updateUI()` method is called.
|
||||
No heavy work is allowed in this method since it runs on the UI thread and it should only update the UI representation using, e.g.,
|
||||
No heavy work is allowed in this method since it runs on EDT, and it should only update the UI representation using, e.g.,
|
||||
`setUIComponentEnabled()` or `setupUIComponentPresentation()` of the provided `ParameterInfoUIContext`.
|
||||
4. After that the following methods are called which will be explained in the next phase: `findElementForUpdatingParameterInfo()`,
|
||||
`updateParameterInfo()`, `updateUI()`.
|
||||
|
@ -101,7 +101,7 @@ myPanel.add(browser.getComponent());
|
||||
#### Loading Documents
|
||||
|
||||
To load a document in the browser, use one of [`JBCefBrowserBase.load*()`](%gh-ic%/platform/platform-api/src/com/intellij/ui/jcef/JBCefBrowserBase.java) methods.
|
||||
Methods loading documents can be called from both UI and non-UI threads.
|
||||
Methods loading documents can be called from both EDT and background threads.
|
||||
It is possible to set an initial URL (passed to constructor or builder) that will be loaded when browser is created and initialized.
|
||||
|
||||
### Browser Client
|
||||
|
Loading…
x
Reference in New Issue
Block a user