toolchains: Run listing tasks on background thread (cherry-pick #21414) (#21421)

gcp-cherry-pick-bot[bot] and Piotr Osiewicz created

Cherry-picked toolchains: Run listing tasks on background thread
(#21414)

Potentially fixes #21404

This is a speculative fix, as while I was trying to repro this issue
I've noticed that introducing artificial delays in ToolchainLister::list
could impact apps responsiveness. These delays were essentially there to
stimulate PET taking a while to find venvs.

Release Notes:

- Improved app responsiveness in environments with multiple Python
virtual environments

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>

Change summary

crates/language/src/toolchain.rs      |  2 +-
crates/languages/src/python.rs        |  2 +-
crates/project/src/toolchain_store.rs | 14 ++++++++------
3 files changed, 10 insertions(+), 8 deletions(-)

Detailed changes

crates/language/src/toolchain.rs 🔗

@@ -22,7 +22,7 @@ pub struct Toolchain {
     pub language_name: LanguageName,
 }
 
-#[async_trait(?Send)]
+#[async_trait]
 pub trait ToolchainLister: Send + Sync {
     async fn list(
         &self,

crates/languages/src/python.rs 🔗

@@ -526,7 +526,7 @@ fn env_priority(kind: Option<PythonEnvironmentKind>) -> usize {
     }
 }
 
-#[async_trait(?Send)]
+#[async_trait]
 impl ToolchainLister for PythonToolchainProvider {
     async fn list(
         &self,

crates/project/src/toolchain_store.rs 🔗

@@ -308,12 +308,14 @@ impl LocalToolchainStore {
                 })
                 .ok()?
                 .await;
-            let language = registry.language_for_name(&language_name.0).await.ok()?;
-            let toolchains = language
-                .toolchain_lister()?
-                .list(root.to_path_buf(), project_env)
-                .await;
-            Some(toolchains)
+
+            cx.background_executor()
+                .spawn(async move {
+                    let language = registry.language_for_name(&language_name.0).await.ok()?;
+                    let toolchains = language.toolchain_lister()?;
+                    Some(toolchains.list(root.to_path_buf(), project_env).await)
+                })
+                .await
         })
     }
     pub(crate) fn active_toolchain(