mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-22 00:00:11 +02:00
task: add more tips + links to spawn_blocking docs (#4150)
This commit is contained in:
@@ -112,27 +112,82 @@ cfg_rt! {
|
||||
/// still spawn additional threads for blocking operations. The basic
|
||||
/// scheduler's single thread is only used for asynchronous code.
|
||||
///
|
||||
/// # Related APIs and patterns for bridging asynchronous and blocking code
|
||||
///
|
||||
/// In simple cases, it is sufficient to have the closure accept input
|
||||
/// parameters at creation time and return a single value (or struct/tuple, etc.).
|
||||
///
|
||||
/// For more complex situations in which it is desirable to stream data to or from
|
||||
/// the synchronous context, the [`mpsc channel`] has `blocking_send` and
|
||||
/// `blocking_recv` methods for use in non-async code such as the thread created
|
||||
/// by `spawn_blocking`.
|
||||
///
|
||||
/// Another option is [`SyncIoBridge`] for cases where the synchronous context
|
||||
/// is operating on byte streams. For example, you might use an asynchronous
|
||||
/// HTTP client such as [hyper] to fetch data, but perform complex parsing
|
||||
/// of the payload body using a library written for synchronous I/O.
|
||||
///
|
||||
/// Finally, see also [Bridging with sync code][bridgesync] for discussions
|
||||
/// around the opposite case of using Tokio as part of a larger synchronous
|
||||
/// codebase.
|
||||
///
|
||||
/// [`Builder`]: struct@crate::runtime::Builder
|
||||
/// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code
|
||||
/// [rayon]: https://docs.rs/rayon
|
||||
/// [`mpsc channel`]: crate::sync::mpsc
|
||||
/// [`SyncIoBridge`]: https://docs.rs/tokio-util/0.6/tokio_util/io/struct.SyncIoBridge.html
|
||||
/// [hyper]: https://docs.rs/hyper
|
||||
/// [`thread::spawn`]: fn@std::thread::spawn
|
||||
/// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout
|
||||
/// [bridgesync]: https://tokio.rs/tokio/topics/bridging
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Pass an input value and receive result of computation:
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::task;
|
||||
///
|
||||
/// # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
|
||||
/// // Initial input
|
||||
/// let mut v = "Hello, ".to_string();
|
||||
/// let res = task::spawn_blocking(move || {
|
||||
/// // do some compute-heavy work or call synchronous code
|
||||
/// "done computing"
|
||||
/// // Stand-in for compute-heavy work or using synchronous APIs
|
||||
/// v.push_str("world");
|
||||
/// // Pass ownership of the value back to the asynchronous context
|
||||
/// v
|
||||
/// }).await?;
|
||||
///
|
||||
/// assert_eq!(res, "done computing");
|
||||
/// // `res` is the value returned from the thread
|
||||
/// assert_eq!(res.as_str(), "Hello, world");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Use a channel:
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::task;
|
||||
/// use tokio::sync::mpsc;
|
||||
///
|
||||
/// # async fn docs() {
|
||||
/// let (tx, mut rx) = mpsc::channel(2);
|
||||
/// let start = 5;
|
||||
/// let worker = task::spawn_blocking(move || {
|
||||
/// for x in 0..10 {
|
||||
/// // Stand in for complex computation
|
||||
/// tx.blocking_send(start + x).unwrap();
|
||||
/// }
|
||||
/// });
|
||||
///
|
||||
/// let mut acc = 0;
|
||||
/// while let Some(v) = rx.recv().await {
|
||||
/// acc += v;
|
||||
/// }
|
||||
/// assert_eq!(acc, 95);
|
||||
/// worker.await.unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg_attr(tokio_track_caller, track_caller)]
|
||||
pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user