CodeBlanks Logo Icon CodeBlanks

select!

tokio::select! ile birden çok future'ı aynı anda beklersin.

select!

tokio::select!, birden çok Future'ı aynı anda bekler ve ilk tamamlananın kolunu çalıştırır; diğerleri iptal edilir. Zaman aşımı ve iptal desenlerinin temelidir:

tokio::select! {
    mesaj = rx.recv() => println!("geldi: {mesaj:?}"),
    _ = tokio::time::sleep(Duration::from_secs(1)) => println!("zaman aşımı"),
    _ = tokio::signal::ctrl_c() => println!("kapatılıyor"),
}

Yalnızca zaman aşımı için daha kısa bir araç da vardır: tokio::time::timeout(süre, future).await.

std karşılığı: zaman aşımlı bekleme

Std kanallarında recv_timeout, mesaj ile süre arasında bir "yarış" kurar:

use std::sync::mpsc::{self, RecvTimeoutError};
use std::time::Duration;

match rx.recv_timeout(Duration::from_millis(500)) {
    Ok(m) => println!("geldi: {m}"),
    Err(RecvTimeoutError::Timeout) => println!("zaman aşımı"),
    Err(RecvTimeoutError::Disconnected) => println!("gönderici kapandı"),
}

Uygulama Zaman aşımı

Bir thread 10 ms uyuyup "hazır" göndersin; recv_timeout(500 ms) ile al. İkinci bir kanalda göndericiyi canlı tutup hiçbir şey gönderme ve recv_timeout(10 ms) ile bekle. İki sonucu {:?} ile boşlukla yazdır.

Başlangıç kodu

main.rs
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(10));
        tx.send("hazır").unwrap();
    });
    let a = rx.recv_timeout(Duration::from_millis(500));

    let (_tx2, rx2) = mpsc::channel::<&str>();
    let b = rx2.recv_timeout(Duration::from_millis(10));
    println!("{:?} {:?}", a, b);
}

Beklenen çıktı

Ok("hazır") Err(Timeout)

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 select!'te kaybeden Future'a ne olur?

  • Panic
  • Bırakılır (drop edilir); yaptığı yarım iş iptal olur Doğru cevap
  • Arka planda tamamlanır
  • Sonraki select!'te devam eder

Açıklama: Bu yüzden select! içindeki Future'ların iptale güvenli (cancel-safe) olması önemlidir.

2 Süreli bekle

Soru
match rx.____(Duration::from_millis(500)) {
    Ok(m) => println!("{m}"),
    Err(_) => println!("zaman aşımı"),
}
Cevap
match rx.recv_timeout(Duration::from_millis(500)) {
    Ok(m) => println!("{m}"),
    Err(_) => println!("zaman aşımı"),
}

Açıklama: recv_timeout, süre dolarsa Timeout hatası döndürür.

3 Durum ve sonuç

Kavram Anlamı
Mesaj süreden önce Ok(mesaj)
Süre doldu Err(Timeout)
Gönderici kapandı Err(Disconnected)
select! kaybeden Drop edilir

İleri seviye bölümündeki tüm dersler