Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Функция unblock

Источник: Документация blocking::unblock

#![allow(unused)]
fn main() {
pub fn unblock<T, F>(f: F) -> Task<T>
where
    F: FnOnce() -> T + Send + 'static,
    T: Send + 'static,
}

Выполняет блокирующий код в пуле потоков.

Описание

Функция unblock позволяет выполнять блокирующие операции в асинхронном контексте, перемещая их в специальный пул потоков. Это предотвращает блокировку асинхронного исполнителя длительными операциями.

Примеры

Чтение содержимого файла:

#![allow(unused)]
fn main() {
use blocking::unblock;
use std::fs;

let contents = unblock(|| fs::read_to_string("file.txt")).await?;
}

Запуск процесса:

#![allow(unused)]
fn main() {
use blocking::unblock;
use std::process::Command;

let out = unblock(|| Command::new("dir").output()).await?;
}

Особенности

Требования к параметрам

  • F: FnOnce() -> T + Send + 'static - замыкание должно быть выполняемым один раз, передаваемым между потоками и иметь статическое время жизни
  • T: Send + 'static - результат должен быть передаваемым между потоками и иметь статическое время жизни

Пул потоков

  • Выделенные потоки: Использует специальный пул потоков для блокирующих операций
  • Автоматическое управление: Потоки управляются автоматически
  • Изоляция: Предотвращает блокировку асинхронного исполнителя

Примеры использования

Работа с файловой системой

#![allow(unused)]
fn main() {
use blocking::unblock;
use std::fs;

// Чтение файла
let data = unblock(|| fs::read("data.bin")).await?;

// Запись файла
unblock(|| fs::write("output.txt", "Hello world")).await?;

// Создание директории
unblock(|| fs::create_dir_all("path/to/dir")).await?;
}

Вычисления в фоне

#![allow(unused)]
fn main() {
use blocking::unblock;

// Ресурсоемкие вычисления
let result = unblock(|| {
    let mut sum = 0;
    for i in 0..1_000_000 {
        sum += i;
    }
    sum
}).await;

println!("Сумма: {}", result);
}

Сетевые операции

#![allow(unused)]
fn main() {
use blocking::unblock;
use std::net::TcpStream;
use std::io::Write;

let response = unblock(|| {
    let mut stream = TcpStream::connect("example.com:80")?;
    stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")?;
    
    let mut response = String::new();
    std::io::Read::read_to_string(&mut stream, &mut response)?;
    Ok::<String, std::io::Error>(response)
}).await?;
}

Работа с базами данных

#![allow(unused)]
fn main() {
use blocking::unblock;

let users = unblock(|| {
    // Блокирующие операции с БД
    // query_database("SELECT * FROM users")
    vec!["user1", "user2", "user3"] // заглушка
}).await;

for user in users {
    println!("Пользователь: {}", user);
}
}

Совместное использование с другими асинхронными операциями

#![allow(unused)]
fn main() {
use blocking::unblock;
use smol::Timer;
use std::time::Duration;

async fn process_data() -> Result<(), Box<dyn std::error::Error>> {
    // Асинхронное ожидание
    Timer::after(Duration::from_secs(1)).await;
    
    // Блокирующая операция
    let data = unblock(|| std::fs::read_to_string("data.txt")).await?;
    
    // Другая асинхронная операция
    Timer::after(Duration::from_millis(500)).await;
    
    // Еще одна блокирующая операция
    unblock(|| std::fs::write("processed.txt", data.to_uppercase())).await?;
    
    Ok(())
}
}

Обработка ошибок

#![allow(unused)]
fn main() {
use blocking::unblock;

let result = unblock(|| -> Result<String, std::io::Error> {
    std::fs::read_to_string("missing_file.txt")
}).await;

match result {
    Ok(contents) => println!("Содержимое: {}", contents),
    Err(e) => println!("Ошибка: {}", e),
}
}

Преимущества

  • Не блокирует исполнитель: Блокирующие операции выполняются в отдельных потоках
  • Простота использования: Знакомый синтаксис с await
  • Безопасность: Гарантии типов Send + 'static
  • Интеграция: Легко комбинируется с другим асинхронным кодом

Альтернативы

Для длительных операций с состоянием рассмотрите использование Unblock<T>:

#![allow(unused)]
fn main() {
use blocking::Unblock;
use std::fs::File;

let file = Unblock::new(File::open("data.txt")?);
// Множественные операции с файлом через асинхронный интерфейс
}